<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>前端面试宝典(自用) | 方歌阙的博客</title>
    <meta name="generator" content="VuePress 1.5.0">
    <link rel="icon" href="/touxiang2.jpg">
    <meta name="description" content="方歌阙 维基百科">
    <link rel="preload" href="/assets/css/0.styles.f2d9e938.css" as="style"><link rel="preload" href="/assets/js/app.395fbd21.js" as="script"><link rel="preload" href="/assets/js/2.cdd4cc35.js" as="script"><link rel="preload" href="/assets/js/10.69995dd9.js" as="script"><link rel="prefetch" href="/assets/js/3.6437e748.js"><link rel="prefetch" href="/assets/js/4.c46efd11.js"><link rel="prefetch" href="/assets/js/5.786e34a2.js"><link rel="prefetch" href="/assets/js/6.23cdc19e.js"><link rel="prefetch" href="/assets/js/7.dac469cc.js"><link rel="prefetch" href="/assets/js/8.9db5607c.js"><link rel="prefetch" href="/assets/js/9.44340b37.js">
    <link rel="stylesheet" href="/assets/css/0.styles.f2d9e938.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">方歌阙的博客</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link">
  首页
</a></div><div class="nav-item"><a href="/view/tech/" class="nav-link router-link-active">
  面试宝典
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="踩过的坑" class="dropdown-title"><span class="title">踩过的坑</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/view/javascript/" class="nav-link">
  javascript
</a></li></ul></div></div><div class="nav-item"><a href="https://www.jianshu.com/u/c455567c7f50" target="_blank" rel="noopener noreferrer" class="nav-link external">
  简书主页
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Concat" class="dropdown-title"><span class="title">Concat</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://segmentfault.com/u/mulander" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Segmentfault
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="GitHub" class="dropdown-title"><span class="title">GitHub</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://github.com/Mulander-J" target="_blank" rel="noopener noreferrer" class="nav-link external">
  GitHub首页
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li class="dropdown-item"><!----> <a href="https://mulander-j.github.io/island/code/html/index.html" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Island
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li class="dropdown-item"><!----> <a href="https://mulander-j.github.io/timeWaster/demo/index.html#/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  TimeWaster
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/" class="nav-link">
  首页
</a></div><div class="nav-item"><a href="/view/tech/" class="nav-link router-link-active">
  面试宝典
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="踩过的坑" class="dropdown-title"><span class="title">踩过的坑</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/view/javascript/" class="nav-link">
  javascript
</a></li></ul></div></div><div class="nav-item"><a href="https://www.jianshu.com/u/c455567c7f50" target="_blank" rel="noopener noreferrer" class="nav-link external">
  简书主页
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Concat" class="dropdown-title"><span class="title">Concat</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://segmentfault.com/u/mulander" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Segmentfault
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="GitHub" class="dropdown-title"><span class="title">GitHub</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://github.com/Mulander-J" target="_blank" rel="noopener noreferrer" class="nav-link external">
  GitHub首页
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li class="dropdown-item"><!----> <a href="https://mulander-j.github.io/island/code/html/index.html" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Island
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li><li class="dropdown-item"><!----> <a href="https://mulander-j.github.io/timeWaster/demo/index.html#/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  TimeWaster
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li></ul></div></div> <!----></nav>  <ul class="sidebar-links"><li><a href="/view/tech/" aria-current="page" class="sidebar-link">前端面试宝典</a></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="前端面试宝典-自用"><a href="#前端面试宝典-自用" class="header-anchor">#</a> 前端面试宝典(自用)</h1> <my-button></my-button> <h2 id="前言"><a href="#前言" class="header-anchor">#</a> 前言</h2> <p>经过艰苦卓绝的面试历程，终于拿到了心仪的offer。期间总结了一些面试题供各位参考，涵盖面很广，并且面的都是知名大厂，所以这些题还是很有代表性的，都掌握以后一面基础面应该没什么问题，二面也能应付大半，奉上：</p> <h2 id="css相关"><a href="#css相关" class="header-anchor">#</a> css相关</h2> <h3 id="_1-万能居中"><a href="#_1-万能居中" class="header-anchor">#</a> 1. 万能居中</h3> <p>1.margin: 0 auto;水平
2.text-align: center;水平
3.行高，垂直
4.表格，center,middle；水平垂直
5.display:table-cell；模拟表格，all
6.绝对定位，50%减自身宽高
7.绝对定位，上下左右全0，margin:auto
8.绝对定位加相对定位。不需要知道宽高
9.IE6，IE7：给父元素设一个font-size:高度/1.14,vertical-align:middle</p> <h3 id="_2-bfc优化"><a href="#_2-bfc优化" class="header-anchor">#</a> 2. <a href="https://www.jianshu.com/p/0d713b32cd0d" target="_blank" rel="noopener noreferrer">BFC优化<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p>块格式化上下文, 特性:</p> <ul><li>使 BFC 内部浮动元素不会到处乱跑（清除浮动）；</li> <li>和浮动元素产生边界（在非浮动元素加margin）。</li></ul> <h3 id="_3-盒模型哪两种模式？什么区别？如何设置"><a href="#_3-盒模型哪两种模式？什么区别？如何设置" class="header-anchor">#</a> 3. 盒模型哪两种模式？什么区别？如何设置</h3> <ul><li>标准模式: box-sizing: content-box(默认); 宽高不包括内边距和边框</li> <li>怪异模式: box-sizing: border-box</li></ul> <h3 id="_4-常用清除浮动的方法，如不清除浮动会怎样？"><a href="#_4-常用清除浮动的方法，如不清除浮动会怎样？" class="header-anchor">#</a> 4. <a href="https://blog.csdn.net/h_qingyi/article/details/81269667" target="_blank" rel="noopener noreferrer">常用清除浮动的方法，如不清除浮动会怎样？<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p>当父元素不给高度的时候，内部元素不浮动时会撑开, 而浮动的时候，父元素变成一条线, 造成塌陷.</p> <ul><li>额外标签法（在最后一个浮动标签后，新加一个标签，给其设置clear：both；）（不推荐）</li> <li>父元素添加overflow:hidden; (触发BFC)</li> <li>使用after伪元素清除浮动（推荐使用）</li> <li>使用before和after双伪元素清除浮动</li></ul> <h3 id="_5-删格化的原理"><a href="#_5-删格化的原理" class="header-anchor">#</a> 5. 删格化的原理</h3> <p>比如antd的row和col, 将一行等分为24份, col是几就占几份, 底层按百分比实现; 结合媒体查询, 可以实现响应式</p> <h3 id="_6-纯css实现三角形"><a href="#_6-纯css实现三角形" class="header-anchor">#</a> 6. 纯css实现三角形</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 通过设置border
.box
        {
            width:0px;
            height:0px;

            border-top:50px solid rgba(0,0,0,0);
            border-right:50px solid  rgba(0,0,0,0);
            border-bottom:50px solid green;
            border-left:50px solid  rgba(0,0,0,0);
            }
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><h3 id="_7-高度不定，宽100-，内一div高不确定，如何实现垂直居中？"><a href="#_7-高度不定，宽100-，内一div高不确定，如何实现垂直居中？" class="header-anchor">#</a> 7. 高度不定，宽100%，内一div高不确定，如何实现垂直居中？</h3> <ul><li>verticle-align: middle;</li> <li>绝对定位50%加translateY(-50%)</li> <li>绝对定位，上下左右全0，margin:auto</li></ul> <h3 id="_8-至少两种方式实现自适应布局"><a href="#_8-至少两种方式实现自适应布局" class="header-anchor">#</a> 8. 至少两种方式实现自适应布局</h3> <ul><li>rem, em</li> <li>vh, vw</li> <li>百分比</li> <li>媒体查询</li> <li>bs, antd等的栅格布局</li></ul> <h3 id="_9-设置一段文字的大小为6px"><a href="#_9-设置一段文字的大小为6px" class="header-anchor">#</a> 9. 设置一段文字的大小为6px</h3> <ul><li>谷歌最小12px, 其他浏览器可以更小</li> <li>通过transform: scale实现</li></ul> <h3 id="_10-css菊花图"><a href="#_10-css菊花图" class="header-anchor">#</a> 10. <a href="https://blog.csdn.net/candy_home/article/details/81540247" target="_blank" rel="noopener noreferrer">css菊花图<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p>四个小圆点一直旋转</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 父标签
animation: antRotate 1.2s infinite linear;
// 子标签
animation: antSpin 1s infinite linear;
@keyframe antSpin {
  to {
    opacity: 1 
  }
}
@keyframe antRotate {
  to {
    transform: rotate(405)
  }
}
// animation-delay: 逐个延迟0.4s
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><h3 id="_11-关于em"><a href="#_11-关于em" class="header-anchor">#</a> 11. 关于em</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code> &lt;div style=&quot;font-size: 20px&quot;&gt;
      123
      &lt;div style=&quot;font-size: 2em;width: 2em&quot;&gt;456&lt;/div&gt;
 &lt;/div&gt;
// 此时子元素的font-size为40px, 宽度为80px(还要乘以子元素font-size的系数)
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h3 id="_12-关于vh-vw"><a href="#_12-关于vh-vw" class="header-anchor">#</a> 12. 关于vh, vw</h3> <p>vw：viewpoint width，视窗宽度，1vw等于视窗宽度的1%。
vh：viewpoint height，视窗高度，1vh等于视窗高度的1%。
vmin：vw和vh中较小的那个。
vmax：vw和vh中较大的那个。</p> <h3 id="_13-flex布局"><a href="#_13-flex布局" class="header-anchor">#</a> 13. <a href="https://www.runoob.com/w3cnote/flex-grammar.html" target="_blank" rel="noopener noreferrer">Flex布局<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>flex-direction控制主副轴</li> <li>flex-wrap控制换行(默认不换行)</li> <li>flex-flow是上两个的结合</li> <li>justify-content主轴对齐方式</li> <li>align-items交叉轴对齐方式</li></ul> <h3 id="_14-overflow原理"><a href="#_14-overflow原理" class="header-anchor">#</a> 14. <a href="https://www.jianshu.com/p/7e04ed3f4bea" target="_blank" rel="noopener noreferrer">overflow原理<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li><code>overflow: hidden</code>能清除块内子元素的浮动影响. 因为该属性进行超出隐藏时需要计算盒子内所有元素的高度, 所以会隐式清除浮动</li> <li>创建BFC条件(满足一个):
<ul><li>float的值不为none；</li> <li>overflow的值不为visible；</li> <li>position的值为fixed / absolute；</li> <li>display的值为table-cell / table-caption / inline-block / flex / inline-flex。</li></ul></li></ul> <h3 id="_15-实现自适应的正方形"><a href="#_15-实现自适应的正方形" class="header-anchor">#</a> 15. 实现自适应的正方形:</h3> <ul><li>使用vw, vh</li> <li><code>width</code>百分比, <code>height: 0</code>, <code>padding-top(bottom): 50%</code></li></ul> <h3 id="_16-标准模式和怪异模式"><a href="#_16-标准模式和怪异模式" class="header-anchor">#</a> 16. 标准模式和怪异模式</h3> <ul><li>document.compatMode属性可以判断是否是标准模式，当 document.compatMode为“CSS1Compat”，是标准模式，“BackCompat”是怪异模式。</li> <li>怪异模式是为了兼容旧版本的浏览器, 因为IE低版本document.documentElement.clientWidth获取不到</li> <li>怪异模式盒模型: <code>box-sizing: border-box</code>; 标准模式: <code>box-sizing: content-box</code></li></ul> <h3 id="_17-css3实现环形进度条"><a href="#_17-css3实现环形进度条" class="header-anchor">#</a> 17. CSS3实现环形进度条</h3> <p>两个对半矩形遮罩, 使用<code>rotate</code>以及<code>overflow: hidden</code>进行旋转</p> <h3 id="_18-css优先级"><a href="#_18-css优先级" class="header-anchor">#</a> 18. <a href="https://www.cnblogs.com/wangmeijian/p/4207433.html" target="_blank" rel="noopener noreferrer">css优先级<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p>选择器的特殊性值表述为4个部分，用0,0,0,0表示。</p> <ul><li>ID选择器的特殊性值，加0,1,0,0。</li> <li>类选择器、属性选择器或伪类，加0,0,1,0。</li> <li>元素和伪元素，加0,0,0,1。</li> <li>通配选择器*对特殊性没有贡献，即0,0,0,0。</li> <li>最后比较特殊的一个标志!important（权重），它没有特殊性值，但它的优先级是最高的，为了方便记忆，可以认为它的特殊性值为1,0,0,0,0。</li></ul> <h2 id="js相关"><a href="#js相关" class="header-anchor">#</a> JS相关</h2> <h3 id="_1-es5和es6继承方式区别"><a href="#_1-es5和es6继承方式区别" class="header-anchor">#</a> 1. ES5和ES6继承方式区别</h3> <ul><li>ES5定义类以函数形式, 以prototype来实现继承</li> <li>ES6以class形式定义类, 以extend形式继承</li></ul> <h3 id="_2-generator了解"><a href="#_2-generator了解" class="header-anchor">#</a> 2. <a href="http://es6.ruanyifeng.com/#docs/generator" target="_blank" rel="noopener noreferrer">Generator了解<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p>ES6 提供的一种异步编程解决方案, Generator 函数是一个状态机，封装了多个内部状态。</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}

var hw = helloWorldGenerator();
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>调用后返回指向内部状态的指针, 调用next()才会移向下一个状态, 参数:</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>hw.next()
// { value: 'hello', done: false }

hw.next()
// { value: 'world', done: false }

hw.next()
// { value: 'ending', done: true }

hw.next()
// { value: undefined, done: true }
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><h3 id="_3-手写promise实现"><a href="#_3-手写promise实现" class="header-anchor">#</a> 3. 手写Promise实现</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>var myPromise = new Promise((resolve, reject) =&gt; {
  // 需要执行的代码
  ...
  if (/* 异步执行成功 */) {
    resolve(value)
  } else if (/* 异步执行失败 */) {
    reject(error)
  }
})

myPromise.then((value) =&gt; {
  // 成功后调用, 使用value值
}, (error) =&gt; {
  // 失败后调用, 获取错误信息error
})
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><h3 id="_4-promise优缺点"><a href="#_4-promise优缺点" class="header-anchor">#</a> 4. Promise优缺点</h3> <ul><li>优点: 解决回调地狱, 对异步任务写法更标准化与简洁化</li> <li>缺点: 首先，无法取消Promise，一旦新建它就会立即执行，无法中途取消; 其次，如果不设置回调函数，Promise内部抛出的错误，不会反应到外部; 第三，当处于pending状态时，无法得知目前进展到哪一个阶段（刚刚开始还是即将完成).
极简版promise封装:</li></ul> <div class="language- line-numbers-mode"><pre class="language-text"><code>function promise () {
  this.msg = '' // 存放value和error
  this.status = 'pending'
  var that = this
  var process = arguments[0]

  process (function () {
    that.status = 'fulfilled'
    that.msg = arguments[0]
  }, function () {
    that.status = 'rejected'
    that.msg = arguments[0]
  })
  return this
}

promise.prototype.then = function () {
  if (this.status === 'fulfilled') {
    arguments[0](this.msg)
  } else if (this.status === 'rejected' &amp;&amp; arguments[1]) {
    arguments[1](this.msg)
  }
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div><h3 id="_5-观察者模式"><a href="#_5-观察者模式" class="header-anchor">#</a> 5. <a href="https://www.cnblogs.com/gradolabs/p/4786782.html" target="_blank" rel="noopener noreferrer">观察者模式<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p>又称发布-订阅模式, 举例子说明.
实现: 发布者管理订阅者队列, 并有新消息推送功能. 订阅者仅关注更新就行</p> <h3 id="_6-手写实现bind"><a href="#_6-手写实现bind" class="header-anchor">#</a> 6. 手写实现bind</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>Function.prototype.bind = function () {
   // 保存原函数
  var self = this
  // 取出第一个参数作为上下文, 相当于[].shift.call(arguments)
  var context = Array.prototype.shift.call(arguments)
  // 取剩余的参数作为arg; 因为arguments是伪数组, 所以要转化为数组才能使用数组方法
  var arg = Array.prototype.slice.call(arguments)
  // 返回一个新函数
  return function () {
    // 绑定上下文并传参
    self.apply(context, Array.prototype.concat.call(arg, Array.prototype.slice.call(arguments)))
  }
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><h3 id="_7-手写实现4种继承"><a href="#_7-手写实现4种继承" class="header-anchor">#</a> 7. <a href="https://www.jianshu.com/p/159b07f2d877" target="_blank" rel="noopener noreferrer">手写实现4种继承<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>function Father () {}
function Child () {}
// 1. 原型继承
Child.prototype = new Father()
// 2. 构造继承
function Child (name) {
  Father.call(this, name)
}
// 3. 组合继承
function Child (name) {
  Father.call(this, name)
}
Child.prototype = new Father()
// 4. 寄生继承
function cloneObj (o) {
  var clone = object.create(o)
  clone.sayName = ...
  return clone
}
// 5. 寄生组合继承
// 6. ES6 class extend继承
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div><h3 id="_9-http状态码"><a href="#_9-http状态码" class="header-anchor">#</a> 9. http状态码</h3> <ul><li>1**: 服务器收到请求, 需请求者进一步操作</li> <li>2**: 请求成功</li> <li>3**: 重定向, 资源被转移到其他URL了</li> <li>4**: 客户端错误, 请求语法错误或没有找到相应资源</li> <li>5**: 服务端错误, server error</li> <li>304:  Not Modified. 指定日期后未修改, 不返回资源</li></ul> <h3 id="_10-object-create实现（原型式继承，特点：实例的-proto-指向构造函数本身）"><a href="#_10-object-create实现（原型式继承，特点：实例的-proto-指向构造函数本身）" class="header-anchor">#</a> 10. Object.create实现（原型式继承，特点：实例的__proto__指向构造函数本身）</h3> <h3 id="_11-async和await：-es8"><a href="#_11-async和await：-es8" class="header-anchor">#</a> 11. async和await：(ES8)</h3> <ul><li>Generator函数的语法糖，将*改成async，将yield换成await。</li> <li>是对Generator函数的改进, 返回promise。</li> <li>异步写法同步化，遇到await先返回，执行完异步再执行接下来的.</li> <li>内置执行器, 无需next()</li></ul> <h3 id="_12-算法和数据结构："><a href="#_12-算法和数据结构：" class="header-anchor">#</a> 12. 算法和数据结构：</h3> <ul><li>算法：
解决具体问题所需要的解决方法。执行效率最快的最优算法。时间复杂度。输入，输出，有穷性，确定性，可行性。冒泡排序，二叉树遍历，最长回文，二分查找，指针，链表等，堆栈，队列等。力扣，codewar，算法导论。</li> <li>数据结构：
逻辑结构：集合、线性、树形、图形结构
物理结构：顺序、链式存储结构</li></ul> <h3 id="_13-封装jsonp"><a href="#_13-封装jsonp" class="header-anchor">#</a> 13. 封装JSONP</h3> <p><img src="https://upload-images.jianshu.io/upload_images/13102777-68b5f178736feab6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="jsonp"></p> <div class="language- line-numbers-mode"><pre class="language-text"><code>function jsonp ({url, param, callback}) {
  return new Promise((resolve, reject) =&gt; {
    var script = document.createElement('script')
    window.callback = function (data) {
      resolve(data)
      document.body.removeChild('script')
    }
    var param = {...param, callback}
    var arr = []
    for (let key in param) {
      arr.push(`${key}=${param[key]}`)
    }
    script.src = `${url}?${arr.join('&amp;')}`
    document.body.appendChild(script)
  })
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><h3 id="_14-手动实现map-foreach以及filter也类似"><a href="#_14-手动实现map-foreach以及filter也类似" class="header-anchor">#</a> 14. 手动实现map(forEach以及filter也类似)</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>// for循环实现
Array.prototype.myMap = function () {
  var arr = this
  var [fn, thisValue] = Array.prototype.slice.call(arguments)
  var result = []
  for (var i = 0; i &lt; arr.length; i++) {
    result.push(fn.call(thisValue, arr[i], i, arr))
  }
  return result
}
var arr0 = [1, 2, 3]
console.log(arr0.myMap(v =&gt; v + 1))

// forEach实现(reduce类似)
Array.prototype.myMap = function (fn, thisValue) {
  var result = []
  this.forEach((v, i, arr) =&gt; {
    result.push(fn.call(thisValue, v, i, arr))
  })
  return result
}
var arr0 = [1, 2, 3]
console.log(arr0.myMap(v =&gt; v + 1))
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div><h3 id="_15-js实现checkbox全选以及反选"><a href="#_15-js实现checkbox全选以及反选" class="header-anchor">#</a> 15. js实现checkbox全选以及反选</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;body&gt;
    &lt;button id=&quot;other&quot;&gt;反选&lt;/button&gt;
    &lt;input type=&quot;checkbox&quot; id=&quot;all&quot; /&gt;全选
    &lt;input type=&quot;checkbox&quot; class=&quot;check&quot; /&gt;1
    &lt;input type=&quot;checkbox&quot; class=&quot;check&quot; /&gt;2
    &lt;input type=&quot;checkbox&quot; class=&quot;check&quot; /&gt;3
    &lt;script&gt;
      var checkbox = document.getElementsByClassName('check')
      var checkAll = document.getElementById('all')
      var checkOther = document.getElementById('other')
      checkAll.onclick = function() {
        var flag = true
        for (var i = 0; i &lt; checkbox.length; i++) {
          if (!checkbox[i].checked) flag = false
        }
        if (flag) {
          for (var i = 0; i &lt; checkbox.length; i++) {
            checkbox[i].checked = false
          }
        } else {
          for (var i = 0; i &lt; checkbox.length; i++) {
            checkbox[i].checked = true
          }
        }
      }
      checkOther.onclick = function() {
        for (var i = 0; i &lt; checkbox.length; i++) {
          checkbox[i].checked = !checkbox[i].checked
        }
      }
    &lt;/script&gt;
  &lt;/body&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br></div></div><h3 id="_16-对原型链的理解？prototype上都有哪些属性"><a href="#_16-对原型链的理解？prototype上都有哪些属性" class="header-anchor">#</a> 16. <a href="https://www.jianshu.com/p/17b2d4dd6867" target="_blank" rel="noopener noreferrer">对原型链的理解<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>？prototype上都有哪些属性</h3> <ul><li>在js里，继承机制是原型继承。继承的起点是 对象的原型（Object prototype）。</li> <li>一切皆为对象，只要是对象，就会有 proto 属性，该属性存储了指向其构造的指针。</li> <li>Object prototype也是对象，其 proto 指向null。</li> <li>对象分为两种：函数对象和普通对象，只有函数对象拥有『原型』对象（prototype）。</li> <li>prototype的本质是普通对象。</li> <li>Function prototype比较特殊，是没有prototype的函数对象。</li> <li>new操作得到的对象是普通对象。</li> <li>当调取一个对象的属性时，会先在本身查找，若无，就根据 proto 找到构造原型，若无，继续往上找。最后会到达顶层Object prototype，它的 proto 指向null，均无结果则返回undefined，结束。</li> <li>由 proto 串起的路径就是『原型链』。</li> <li>通过prototype可以给所有子类共享属性</li> <li>函数（Function）才有prototype属性，对象（除Object）拥有__proto__</li> <li>实例的__proto__等于构造函数的prototype</li> <li>实例的constructor指向构造函数</li></ul> <h3 id="_17-为什么使用继承"><a href="#_17-为什么使用继承" class="header-anchor">#</a> 17. 为什么使用继承</h3> <p>通常在一般的项目里不需要,因为应用简单,但你要用纯js做一些复杂的工具或框架系统就要用到了,比如webgis、或者js框架如jquery、ext什么的,不然一个几千行代码的框架不用继承得写几万行,甚至还无法维护</p> <h3 id="_18-settimeout时间延迟为何不准"><a href="#_18-settimeout时间延迟为何不准" class="header-anchor">#</a> 18. setTimeout时间延迟为何不准</h3> <p>单线程, 先执行同步主线程, 再执行异步任务队列</p> <h3 id="_19-事件循环述，宏任务和微任务有什么区别？"><a href="#_19-事件循环述，宏任务和微任务有什么区别？" class="header-anchor">#</a> 19. <a href="https://www.jianshu.com/p/03b89adb3ddd" target="_blank" rel="noopener noreferrer">事件循环述，宏任务和微任务有什么区别？<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>先主线程后异步任务队列</li> <li>先微任务再宏任务</li></ul> <h3 id="_20-let-const-var作用域"><a href="#_20-let-const-var作用域" class="header-anchor">#</a> 20. let const var作用域</h3> <p>块级作用域, 暂时性死区</p> <h3 id="_21-节流和防抖"><a href="#_21-节流和防抖" class="header-anchor">#</a> 21. <a href="https://www.cnblogs.com/walls/p/6399837.html" target="_blank" rel="noopener noreferrer">节流和防抖<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>函数节流是指一定时间内js方法只跑一次。比如人的眨眼睛，就是一定时间内眨一次。这是函数节流最形象的解释。</li></ul> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 函数节流   滚动条滚动
var canRun = true;
document.getElementById(&quot;throttle&quot;).onscroll = function(){
    if(!canRun){
        // 判断是否已空闲，如果在执行中，则直接return
        return;
    }

    canRun = false;
    setTimeout(function(){
        console.log(&quot;函数节流&quot;);
        canRun = true;
    }, 300);
};
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><ul><li>函数防抖是指频繁触发的情况下，只有足够的空闲时间，才执行代码一次。比如生活中的坐公交，就是一定时间内，如果有人陆续刷卡上车，司机就不会开车。只有别人没刷卡了，司机才开车。</li></ul> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 函数防抖
var timer = false;
document.getElementById(&quot;debounce&quot;).onscroll = function(){
    clearTimeout(timer); // 清除未执行的代码，重置回初始化状态

    timer = setTimeout(function(){
        console.log(&quot;函数防抖&quot;);
    }, 300);
};  
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><h3 id="_22-实现一个sleep函数"><a href="#_22-实现一个sleep函数" class="header-anchor">#</a> 22. 实现一个sleep函数</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 这种实现方式是利用一个伪死循环阻塞主线程。因为JS是单线程的。所以通过这种方式可以实现真正意义上的sleep()。
function sleep(delay) {
  var start = (new Date()).getTime();
  while ((new Date()).getTime() - start &lt; delay) {
    continue;
  }
}

function test() {
  console.log('111');
  sleep(2000);
  console.log('222');
}

test()
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><h3 id="_23-闭包"><a href="#_23-闭包" class="header-anchor">#</a> 23. 闭包</h3> <ul><li>概念: 内层函数能够访问外层函数作用域的变量</li> <li>缺点: 引起内存泄漏（释放内存）</li> <li>作用:
<ul><li>保护this指向</li> <li>使用闭包修正打印值</li> <li>实现柯里化</li> <li>实现node commonJs 模块化, 实现私有变量</li> <li>保持变量与函数活性, 可延迟回收和执行</li></ul></li></ul> <h3 id="_24-immutable-js"><a href="#_24-immutable-js" class="header-anchor">#</a> 24. <a href="https://www.jianshu.com/p/0fa8c7456c15" target="_blank" rel="noopener noreferrer">Immutable.js<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p>Facebook出品, 倡导数据的不可变性, 用的最多就是List和Map.</p> <h3 id="_25-js实现instanceof"><a href="#_25-js实现instanceof" class="header-anchor">#</a> 25. js实现instanceof</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 检测l的原型链（__proto__）上是否有r.prototype，若有返回true，否则false
function myInstanceof (l, r) {
  var R = r.prototype
  while (l.__proto__) {
    if (l.__proto__ === R) return true
  }
  return false
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><h3 id="_27-es6的模块引入和commonjs区别"><a href="#_27-es6的模块引入和commonjs区别" class="header-anchor">#</a> 27. <a href="https://www.cnblogs.com/unclekeith/archive/2017/10/17/7679503.html" target="_blank" rel="noopener noreferrer">ES6的模块引入和CommonJs区别<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <h3 id="_28-严格模式"><a href="#_28-严格模式" class="header-anchor">#</a> 28. <a href="https://www.jianshu.com/p/39e295f4526d" target="_blank" rel="noopener noreferrer">严格模式<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 严格模式下, 隐式绑定丢失后this不会指向window, 而是指向undefined
      'use strict'
      var a = 2
      var obj = {
        a: 1,
        b: function() {
          // console.log(this.a)
          console.log(this)
        }
      }
      var c = obj.b
      c() // undefined
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><h3 id="_30-typescript缺点"><a href="#_30-typescript缺点" class="header-anchor">#</a> 30. typescript缺点</h3> <ul><li>并不是严格意义的js的超集, 与js不完全兼容, 会报错</li> <li>更多的限制, 是一种桎梏</li> <li>有些js第三方库没有dts, 有问题</li></ul> <h3 id="_31-构造函数实现原理（new操作符做了什么）"><a href="#_31-构造函数实现原理（new操作符做了什么）" class="header-anchor">#</a> 31. 构造函数实现原理（new操作符做了什么）</h3> <ul><li>构造函数中没有显示的创建Object对象,  实际上后台自动创建了一个空对象</li> <li>直接给this对象赋值属性和方法, this即指向创建的对象</li> <li>没有return返回值, 后台自动返回了该对象</li> <li>该对象继承构造函数的原型</li></ul> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 模拟构造函数实现
var Book = function(name) {
  this.name = name;
};
 
//正常用法
var java = new Book(‘Master Java’);
        
//使用代码模拟，在非IE浏览器中测试，IE浏览器不支持
var python = {};
python.__proto__ = Book.prototype;
Book.call(python, 'Master Python');
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><h3 id="_32-for-in-和-for-of区别"><a href="#_32-for-in-和-for-of区别" class="header-anchor">#</a> 32. <a href="https://www.jianshu.com/p/c43f418d6bf0" target="_blank" rel="noopener noreferrer">for in 和 for of区别<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li><code>for in</code>遍历数组会遍历到数组原型上的属性和方法, 更适合遍历对象</li> <li><code>forEach</code>不支持<code>break, continue, return</code>等</li> <li>使用<code>for of</code>可以成功遍历数组的值, 而不是索引, 不会遍历原型</li> <li>for in 可以遍历到myObject的原型方法method,如果不想遍历原型方法和属性的话，可以在循环内部判断一下,hasOwnPropery方法可以判断某属性是否是该对象的实例属性</li></ul> <h3 id="_33-js实现并发控制"><a href="#_33-js实现并发控制" class="header-anchor">#</a> 33. JS实现并发控制:</h3> <p>使用消息队列以及<code>setInterval</code>或<code>promise</code>进行入队和出队</p> <h3 id="_34-ajax和axios、fetch的区别"><a href="#_34-ajax和axios、fetch的区别" class="header-anchor">#</a> 34. <a href="https://www.jianshu.com/p/8bc48f8fde75" target="_blank" rel="noopener noreferrer">ajax和axios、fetch的区别<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <h3 id="_35-promise-finally实现"><a href="#_35-promise-finally实现" class="header-anchor">#</a> 35. promise.finally实现</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  =&gt; P.resolve(callback()).then(() =&gt; value),
    reason =&gt; P.resolve(callback()).then(() =&gt; { throw reason })
  );
};
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><h3 id="_36-实现symbol"><a href="#_36-实现symbol" class="header-anchor">#</a> 36. <a href="https://segmentfault.com/a/1190000015262174" target="_blank" rel="noopener noreferrer">实现symbol<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>(function() {
    var root = this;
    var SymbolPolyfill = function Symbol(description) {
        // Symbol函数前不能使用new命令
        if (this instanceof SymbolPolyfill) throw new TypeError('Symbol is not a constructor')
        // 参数是对象，则调用toString
        var descString = description === undefined ? undefined : String(description)
        var symbol = Object.create({
            // 显示转为字符串
            toString: function() {
                return 'Symbol(' + this.description ')'
            },
            // 不能参与运算
            valueOf: function() {
                throw new Error('Cannot convert a Symbol value')
            }
        })
        // 作为对象键名时，生成一个独一无二名称
        // ES2019新增
        symbol.prototype.description = descString
        // 返回一个新对象 由于指针不同  所以两两不等
        return symbol;
    }
    root.SymbolPolyfill = SymbolPolyfill;
})();
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br></div></div><p><a href="https://www.jianshu.com/p/28d85bebe599" target="_blank" rel="noopener noreferrer">Object.create()创建对象<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p> <h3 id="_37-es6装饰器"><a href="#_37-es6装饰器" class="header-anchor">#</a> 37. ES6装饰器</h3> <ul><li>提案经过大幅修改，没有定案，可能会变</li> <li>是一种函数，用于改变类或方法的功能，起到注释作用</li> <li>函数：</li></ul> <div class="language- line-numbers-mode"><pre class="language-text"><code>@decorator
class A {}

// 等同于

class A {}
A = decorator(A) || A;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><ul><li>方法：</li></ul> <div class="language- line-numbers-mode"><pre class="language-text"><code>function readonly(target, name, descriptor){
  // descriptor对象原来的值如下
  // {
  //   value: specifiedFunction,
  //   enumerable: false,
  //   configurable: true,
  //   writable: true
  // };
  descriptor.writable = false;
  return descriptor;
}

readonly(Person.prototype, 'name', descriptor);
// 类似于
Object.defineProperty(Person.prototype, 'name', descriptor);
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><ul><li>先从外到内进入，经过 reverse 倒序后，然后由内向外执行。</li></ul> <h3 id="_38-实现fetch-abort"><a href="#_38-实现fetch-abort" class="header-anchor">#</a> 38. 实现fetch abort</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>const controller = new AbortController()
setTimeout(() =&gt; controller.abort(), 1000);

fetch(url, {
    signal: controller.signal
}).then(res =&gt; {
    ...   
}, err =&gt; {
    console.log(err) // AbortError
})
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><h3 id="_39-使用xhr实现fetch"><a href="#_39-使用xhr实现fetch" class="header-anchor">#</a> 39. 使用xhr实现fetch</h3> <ul><li>fetch是ajax替代品，基于promise。</li> <li>类似于jquey ajax，但不是ajax封装，而是原生js,，没有使用XHR对象</li> <li>比ajax方便，但仍然不完善，建议使用axios库</li> <li>fetch有而axios没有的问题：
<ul><li>兼容性问题</li> <li>默认不带cookie，需要手动设置credentials</li> <li>跨域问题，需要手动设置mode</li> <li>返回400、500不识别为reject</li> <li>无法abort和timeout</li></ul></li> <li>用XHR实现fetch:</li></ul> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 先实现ajax
function ajax(method,url,data,suc,fail) {
    var xhr = new XMLHttpRequest();
    xhr.open(method, url, true);
    xhr.onreadystatechange = function () {
        if(xhr.readyState == 4){
            if(xhr.status == 200){
                suc(xhr.responseText)
            } else {
                console.log(err);
                fail(xhr.responseText);
            }
        }
    };
    xhr.send(data);
}

// 再实现promise
function promise () {
  this.msg = '' // 存放value和error
  this.status = 'pending'
  var that = this
  var process = arguments[0]

  process (function () {
    that.status = 'fulfilled'
    that.msg = arguments[0]
  }, function () {
    that.status = 'rejected'
    that.msg = arguments[0]
  })
  return this
}

promise.prototype.then = function () {
  if (this.status === 'fulfilled') {
    arguments[0](this.msg)
  } else if (this.status === 'rejected' &amp;&amp; arguments[1]) {
    arguments[1](this.msg)
  }
}

// 最后实现fetch
function fetch(method, url, data) {
    return new promise(function (resolve,reject) {
        ajax(method, url, data, function (res) {
            resolve(res);
        },function (err) {
            reject(err);
        })
    })
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br></div></div><h3 id="_40-js中数值存储"><a href="#_40-js中数值存储" class="header-anchor">#</a> 40. JS中数值存储</h3> <ul><li>javascript 中所有的数值类型都是双精度存储的，使用 <strong>64bit</strong>，64bit 等于 <strong>8byte</strong></li> <li>中文占2个字节（byte） 中文里标点也占2个字节（byte） 英文里的子母不分大小写，一个子母占1个字节（字节） 英文里的标点占1个字节。 1字节（byte）=8位（bits）</li> <li>当任何数字在进行位运算时 js 内部会将其转换成32位有符号整型</li></ul> <h3 id="_41-this指向："><a href="#_41-this指向：" class="header-anchor">#</a> 41. <a href="https://juejin.im/post/5c049e6de51d45471745eb98" target="_blank" rel="noopener noreferrer">this指向<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>：</h3> <ul><li>谁调用了方法，该方法的this就指向谁;</li> <li>优先级：箭头函数 &gt; new绑定 &gt; 显示绑定 &gt; 隐式绑定</li></ul> <h2 id="浏览器网络相关"><a href="#浏览器网络相关" class="header-anchor">#</a> 浏览器网络相关</h2> <h3 id="_1-reflow-回流-和repaint-重绘-优化"><a href="#_1-reflow-回流-和repaint-重绘-优化" class="header-anchor">#</a> 1. <a href="https://www.jianshu.com/p/40c6fc1d4800" target="_blank" rel="noopener noreferrer">reflow(回流)和repaint(重绘)优化<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p><img src="https://upload-images.jianshu.io/upload_images/13102777-332db8d0cb9a4c4c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="render"></p> <ul><li>浏览器渲染过程: DOM tree, CSS tree --&gt; Render tree --&gt; Paint</li> <li>DOM tree根节点为html</li> <li>渲染从浏览器左上角到右下角</li> <li>第一次打开页面至少触发一次重绘和回流, 结构如宽高位置变化时, 触发<strong>reflow回流</strong>;非结构如背景色变化时, 触发<strong>repaint重绘</strong>. 二者都会造成体验不佳</li> <li>如何减少重绘和回流?
<ul><li>通过classname或cssText一次性修改样式, 而非一个一个改</li> <li>离线模式: 克隆要操作的结点, 操作后再与原始结点交换, 类似于虚拟DOM</li> <li>避免频繁直接访问计算后的样式, 而是先将信息保存下来</li> <li>绝对布局的DOM, 不会造成大量reflow</li> <li>div不要嵌套太深, 不要超过六层</li></ul></li></ul> <h3 id="_2-一个页面从输入-url-到页面加载显示完成，这个过程中都发生了什么？"><a href="#_2-一个页面从输入-url-到页面加载显示完成，这个过程中都发生了什么？" class="header-anchor">#</a> 2.<a href="https://www.cnblogs.com/gitbo/p/6597735.html" target="_blank" rel="noopener noreferrer">一个页面从输入 URL 到页面加载显示完成，这个过程中都发生了什么？<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>浏览器根据请求的URL交给DNS域名解析，找到真实IP，向服务器发起请求；
- 服务器交给后台处理完成后返回数据，浏览器接收文件（HTML、JS、CSS、图象等）；</li> <li>浏览器对加载到的资源（HTML、JS、CSS等）进行语法解析，建立相应的内部数据结构（如HTML的DOM Tree）；</li> <li>载入解析到的资源文件，渲染页面，完成。</li></ul> <h3 id="_3-localstorage-与-sessionstorage-与cookie的区别总结"><a href="#_3-localstorage-与-sessionstorage-与cookie的区别总结" class="header-anchor">#</a> 3.localStorage 与 sessionStorage 与cookie的区别总结</h3> <ul><li><strong>共同点</strong>: 都保存在浏览器端, 且同源</li> <li>localStorage 与 sessionStorage 统称webStorage,保存在浏览器,不参与服务器通信,大小为5M</li> <li><strong>生命周期不同</strong>: localStorage永久保存, sessionStorage当前会话, 都可手动清除</li> <li><strong>作用域不同</strong>: 不同浏览器不共享local和session, 不同会话不共享session</li> <li><strong>Cookie</strong>: 设置的过期时间前一直有效, 大小4K.有个数限制, 各浏览器不同, 一般为20个.携带在HTTP头中, 过多会有性能问题.可自己封装, 也可用原生</li></ul> <h3 id="_4-浏览器如何阻止事件传播，阻止默认行为"><a href="#_4-浏览器如何阻止事件传播，阻止默认行为" class="header-anchor">#</a> 4.浏览器如何阻止事件传播，阻止默认行为</h3> <ul><li>阻止事件传播(冒泡): e.stopPropagation()</li> <li>阻止默认行为: e.preventDefault()</li></ul> <h3 id="_5-虚拟dom方案相对原生dom操作有什么优点，实现上是什么原理？"><a href="#_5-虚拟dom方案相对原生dom操作有什么优点，实现上是什么原理？" class="header-anchor">#</a> 5.虚拟DOM方案相对原生DOM操作有什么优点，实现上是什么原理？</h3> <p>虚拟DOM可提升性能, 无须整体重新渲染, 而是局部刷新.
JS对象, diff算法</p> <h3 id="_6-浏览器事件机制中事件触发三个阶段"><a href="#_6-浏览器事件机制中事件触发三个阶段" class="header-anchor">#</a> 6.浏览器事件机制中事件触发三个阶段</h3> <ul><li><strong>事件捕获阶段</strong>: 从dom树节点往下找到目标节点, 不会触发函数</li> <li><strong>事件目标处理函数</strong>: 到达目标节点</li> <li><strong>事件冒泡</strong>: 最后从目标节点往顶层元素传递, 通常函数在此阶段执行.
addEventListener第三个参数默认false(冒泡阶段执行),true(捕获阶段执行).
阻止冒泡见以上方法</li></ul> <h3 id="_7-什么是跨域？为什么浏览器要使用同源策略？你有几种方式可以解决跨域问题？了解预检请求嘛？"><a href="#_7-什么是跨域？为什么浏览器要使用同源策略？你有几种方式可以解决跨域问题？了解预检请求嘛？" class="header-anchor">#</a> 7.<a href="https://segmentfault.com/a/1190000011145364" target="_blank" rel="noopener noreferrer">什么是跨域？为什么浏览器要使用同源策略？你有几种方式可以解决跨域问题？了解预检请求嘛？<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>跨域是指一个域下的文档或脚本试图去请求另一个域下的资源</li> <li>防止XSS、CSFR等攻击, 协议+域名+端口不同</li> <li>jsonp; 跨域资源共享（CORS）(Access control); 服务器正向代理等
<img src="https://upload-images.jianshu.io/upload_images/13102777-9505d1ec2550649f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="jsonp封装"></li> <li><strong>预检请求</strong>: 需预检的请求要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器，以获知服务器是否允许该实际请求。&quot;预检请求“的使用，可以避免跨域请求对服务器的用户数据产生未预期的影响</li></ul> <h3 id="_8-了解浏览器缓存机制吗？"><a href="#_8-了解浏览器缓存机制吗？" class="header-anchor">#</a> 8.<a href="https://www.jianshu.com/p/8b4f3f7bf823" target="_blank" rel="noopener noreferrer">了解浏览器缓存机制吗？<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>浏览器缓存就是把一个已经请求过的资源拷贝一份存储起来，当下次需要该资源时，浏览器会根据缓存机制决定直接使用缓存资源还是再次向服务器发送请求.</li> <li>作用: 减少网络传输的损耗以及降低服务器压力。</li> <li>缓存位置优先级：Service Worker &gt; Memory Cache &gt; Disk Cache &gt; Push Cache. 都没有命中，就会向服务器发请求</li> <li>策略优先级: 强制缓存 &gt; 协商缓存; cache-control &gt; Expires &gt; Etag &gt; Last-modified</li></ul> <h3 id="_9-为什么操作-dom-慢"><a href="#_9-为什么操作-dom-慢" class="header-anchor">#</a> 9.为什么操作 DOM 慢?</h3> <p>DOM本身是一个js对象, 操作这个对象本身不慢, 但是操作后触发了浏览器的行为, 如repaint和reflow等浏览器行为, 使其变慢</p> <h3 id="_10-什么情况会阻塞渲染？"><a href="#_10-什么情况会阻塞渲染？" class="header-anchor">#</a> 10.什么情况会阻塞渲染？</h3> <ul><li>js脚本同步执行</li> <li>css和图片虽然是异步加载, 但js文件执行需依赖css, 所以css也会阻塞渲染</li></ul> <h3 id="_11-如何判断js运行在浏览器中还是node中？"><a href="#_11-如何判断js运行在浏览器中还是node中？" class="header-anchor">#</a> 11.如何判断js运行在浏览器中还是node中？</h3> <p>判断有无全局对象global和window</p> <h3 id="_12-关于web以及浏览器处理预加载有哪些思考？"><a href="#_12-关于web以及浏览器处理预加载有哪些思考？" class="header-anchor">#</a> 12.关于web以及浏览器处理预加载有哪些思考？</h3> <p>图片等静态资源在使用之前就提前请求
资源使用到的时候能从缓存中加载, 提升用户体验
页面展示的依赖关系维护</p> <h3 id="_13-http多路复用"><a href="#_13-http多路复用" class="header-anchor">#</a> 13.<a href="https://segmentfault.com/a/1190000011172823" target="_blank" rel="noopener noreferrer">http多路复用<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li><strong>Keep-Alive</strong>: Keep-Alive解决的核心问题：一定时间内，同一域名多次请求数据，只建立一次HTTP请求，其他请求可复用每一次建立的连接通道，以达到提高请求效率的问题。这里面所说的一定时间是可以配置的，不管你用的是Apache还是nginx。</li> <li>解决两个问题: 串行文件传输(采用二进制数据帧); 连接数过多(采用流, 并行传输)</li></ul> <h3 id="_14-http和https："><a href="#_14-http和https：" class="header-anchor">#</a> 14. <a href="https://www.cnblogs.com/wqhwe/p/5407468.html" target="_blank" rel="noopener noreferrer">http和https：<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>http: 最广泛网络协议，BS模型，浏览器高效。</li> <li>https: 安全版，通过SSL加密，加密传输，身份认证，密钥</li></ul> <ol><li>https相对于http加入了ssl层, 加密传输, 身份认证;</li> <li>需要到ca申请收费的证书;</li> <li>安全但是耗时多，缓存不是很好;</li> <li>注意兼容http和https;</li> <li>连接方式不同, 端口号也不同, http是80, https是443</li></ol> <h3 id="_15-csrf和xss区别及防御"><a href="#_15-csrf和xss区别及防御" class="header-anchor">#</a> 15.  <a href="https://blog.csdn.net/m0_37631322/article/details/81346335" target="_blank" rel="noopener noreferrer">CSRF和XSS区别及防御<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <h3 id="_16-cookie可设置哪些属性？httponly"><a href="#_16-cookie可设置哪些属性？httponly" class="header-anchor">#</a> 16. cookie可设置哪些属性？httponly?</h3> <p>chrome控制台的application下可查看:
<img src="https://upload-images.jianshu.io/upload_images/13102777-01018453748f43b6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="cookie"></p> <ul><li>name　　字段为一个cookie的名称。</li> <li>value　　字段为一个cookie的值。</li> <li>domain　　字段为可以访问此cookie的域名。</li> <li>path　　字段为可以访问此cookie的页面路径。 比如domain是abc.com,path是/test，那么只有/test路径下的页面可以读取此cookie。</li> <li>expires/Max-Age 　　字段为此cookie超时时间。若设置其值为一个时间，那么当到达此时间后，此cookie失效。不设置的话默认值是Session，意思是cookie会和session一起失效。当浏览器关闭(不是浏览器标签页，而是整个浏览器) 后，此cookie失效。</li> <li>Size　　字段 此cookie大小。</li> <li>http　　字段  cookie的httponly属性。若此属性为true，则只有在http请求头中会带有此cookie的信息，而不能通过document.cookie来访问此cookie。</li> <li>secure　　 字段 设置是否只能通过https来传递此条cookie</li></ul> <h3 id="_17-登录后，前端做了哪些工作，如何得知已登录"><a href="#_17-登录后，前端做了哪些工作，如何得知已登录" class="header-anchor">#</a> 17. 登录后，前端做了哪些工作，如何得知已登录</h3> <ul><li>前端存放服务端下发的cookie, 简单说就是写一个字段在cookie中表明已登录, 并设置失效日期</li> <li>或使用后端返回的token, 每次ajax请求将token携带在请求头中, 这也是防范csrf的手段之一</li></ul> <h3 id="_18-http状态码"><a href="#_18-http状态码" class="header-anchor">#</a> 18. <a href="https://www.runoob.com/http/http-status-codes.html" target="_blank" rel="noopener noreferrer">http状态码<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>1**: 服务器收到请求, 需请求者进一步操作</li> <li>2**: 请求成功</li> <li>3**: 重定向, 资源被转移到其他URL了</li> <li>4**: 客户端错误, 请求语法错误或没有找到相应资源</li> <li>5**: 服务端错误, server error</li> <li>301: 资源(网页等)被永久转移到其他URL, 返回值中包含新的URL, 浏览器会自动定向到新URL</li> <li>302: 临时转移. 客户端应访问原有URL</li> <li>304: Not Modified. 指定日期后未修改, 不返回资源</li> <li>403: 服务器拒绝执行请求</li> <li>404: 请求的资源(网页等)不存在</li> <li>500: 内部服务器错误</li></ul> <h3 id="_19-http请求头缓存设置方法"><a href="#_19-http请求头缓存设置方法" class="header-anchor">#</a> 19.  <a href="https://www.cnblogs.com/zhaow/p/7832829.html" target="_blank" rel="noopener noreferrer">Http请求头缓存设置方法<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p>Cache-control, expire, last-modify</p> <h3 id="_20-实现页面回退刷新"><a href="#_20-实现页面回退刷新" class="header-anchor">#</a> 20. 实现页面回退刷新</h3> <ul><li>旧: window.history.back() + window.location.href=document.referrer;</li> <li>新: HTML5的新API扩展了window.history，使历史记录点更加开放了。可以存储当前历史记录点、替换当前历史记录点、监听历史记录点onpopstate, replaceState</li></ul> <h3 id="_21-正向代理和反向代理"><a href="#_21-正向代理和反向代理" class="header-anchor">#</a> 21. <a href="https://www.cnblogs.com/Anker/p/6056540.html" target="_blank" rel="noopener noreferrer">正向代理和反向代理<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>正向代理:
<img src="https://upload-images.jianshu.io/upload_images/13102777-b63e408b48418647.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="正向代理">
（1）访问原来无法访问的资源，如google
（2） 可以做缓存，加速访问资源
（3）对客户端访问授权，上网进行认证
（4）代理可以记录用户访问记录（上网行为管理），对外隐藏用户信息</li> <li>反向代理: <img src="https://upload-images.jianshu.io/upload_images/13102777-78b27e56002ff0ee.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="反向代理">
（1）保证内网的安全，可以使用反向代理提供WAF功能，阻止web攻击大型网站，通常将反向代理作为公网访问地址，Web服务器是内网。
（2）负载均衡，通过反向代理服务器来优化网站的负载</li></ul> <h3 id="_22-关于预检请求"><a href="#_22-关于预检请求" class="header-anchor">#</a> 22. <a href="https://www.jianshu.com/p/3a10ac906fd0" target="_blank" rel="noopener noreferrer">关于预检请求<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p>在非简单请求且跨域的情况下，浏览器会自动发起options预检请求。</p> <h3 id="_23-三次握手四次挥手"><a href="#_23-三次握手四次挥手" class="header-anchor">#</a> 23. <a href="https://www.jianshu.com/p/ad0904df7d76" target="_blank" rel="noopener noreferrer">三次握手四次挥手<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>开启连接用三次握手, 关闭用四次挥手</li></ul> <h3 id="_24-tcp和udp协议"><a href="#_24-tcp和udp协议" class="header-anchor">#</a> 24. TCP和UDP协议</h3> <ul><li>TCP（Transmission Control Protocol：传输控制协议；面向连接，可靠传输</li> <li>UDP（User Datagram Protocol）：用户数据报协议；面向无连接，不可靠传输</li></ul> <h3 id="_25-进程和线程的区别"><a href="#_25-进程和线程的区别" class="header-anchor">#</a> 25. <a href="https://www.cnblogs.com/zhuzhu2016/p/5804875.html" target="_blank" rel="noopener noreferrer">进程和线程的区别<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>进程：是并发执行的程序在执行过程中分配和管理资源的基本单位，是一个动态概念，竞争计算机系统资源的基本单位。</li> <li>线程：是进程的一个执行单元，是进程内科调度实体。比进程更小的独立运行的基本单位。线程也被称为轻量级进程。</li> <li>一个程序至少一个进程，一个进程至少一个线程。</li></ul> <h2 id="vue相关"><a href="#vue相关" class="header-anchor">#</a> vue相关</h2> <h3 id="_1-生命周期"><a href="#_1-生命周期" class="header-anchor">#</a> 1.<a href="http://baijiahao.baidu.com/s?id=1603406094025961442&amp;wfr=spider&amp;for=pc" target="_blank" rel="noopener noreferrer"> 生命周期<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p><img src="https://upload-images.jianshu.io/upload_images/13102777-9983f5ab8e2b6fb3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="生命周期"></p> <h3 id="_2-双向数据绑定v-model。这个最好也是自己实现一下-理解更深"><a href="#_2-双向数据绑定v-model。这个最好也是自己实现一下-理解更深" class="header-anchor">#</a> 2 .双向数据绑定v-model。这个最好也是自己实现一下 理解更深</h3> <p>通过v-model
VUE实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 依赖收集
// 简化版
var obj = { }
var name 
//第一个参数：定义属性的对象。
//第二个参数：要定义或修改的属性的名称。
//第三个参数：将被定义或修改的属性描述符。
Object.defineProperty(obj, &quot;data&quot;, {
  //获取值
  get: function () {
    return name
  },
  //设置值
  set: function (val) {
    name = val
    console.log(val)
  }
})
//赋值调用set
obj.data = 'aaa'
//取值调用get
console.log(obj.data)

// 详细版
 myVue.prototype._obverse = function (obj) { // obj = {number: 0}
    var value;
    for (key in obj) {  //遍历obj对象
      if (obj.hasOwnProperty(key)) {
        value = obj[key]; 
        if (typeof value === 'object') {  //如果值是对象，则递归处理
          this._obverse(value);
        }
        Object.defineProperty(this.$data, key, {  //关键
          enumerable: true,
          configurable: true,
          get: function () {
            console.log(`获取${value}`);
            return value;
          },
          set: function (newVal) {
            console.log(`更新${newVal}`);
            if (value !== newVal) {
              value = newVal;
            }
          }
        })
      }
    }
  }
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br></div></div><h3 id="_3-vue父子组件传递参数"><a href="#_3-vue父子组件传递参数" class="header-anchor">#</a> 3.vue父子组件传递参数</h3> <ul><li>父 --&gt;子: 通过props</li> <li>子 --&gt;父: 通过 $$refs 或 $emit</li></ul> <h3 id="_4-vue传递参数方法"><a href="#_4-vue传递参数方法" class="header-anchor">#</a> 4.<a href="https://www.imooc.com/article/257885" target="_blank" rel="noopener noreferrer">vue传递参数方法<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>父子组件传参如上, v-bind :    v-on @</li> <li>兄弟组件传参:(通过EventBus事件总线实现)</li></ul> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 1. 新建eventBus.js
import Vue from 'vue'
export default new Vue
// 或直接在main.js中初始化EventBus(全局)
Vue.prototype.$EventBus = new Vue()

// 2. 发射与接收
// 如果是定义在eventBus.js中
import eventBus from 'eventBus.js'
eventBus.$emit()
eventBus.$on()

// 如果是定义在main.js中
this.bus.$emit()
this.bus.$on()

// 3. 移除监听
eventBus.$off()
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><h3 id="_5-vue自定义组件"><a href="#_5-vue自定义组件" class="header-anchor">#</a> 5.vue自定义组件</h3> <p>可以使用独立可复用的自定义组件来构成大型应用, 采用帕斯卡命名法或横线连接, 通过以上方式进行组件间通信. 每一个组件都是Vue实例, 可以使用生命周期钩子.</p> <h3 id="_6-vue自定义指令"><a href="#_6-vue自定义指令" class="header-anchor">#</a> 6. <a href="http://baijiahao.baidu.com/s?id=1603883371090691442&amp;wfr=spider&amp;for=pc" target="_blank" rel="noopener noreferrer">vue自定义指令<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>除核心指令之外的指令, 使用directive进行注册.</li> <li>指令自定义钩子函数: bind, inserted, update, componentUpdated, unbind</li></ul> <h3 id="_7-vuex组成和原理"><a href="#_7-vuex组成和原理" class="header-anchor">#</a> 7.<a href="https://baijiahao.baidu.com/s?id=1618794879569468435&amp;wfr=spider&amp;for=pc" target="_blank" rel="noopener noreferrer">vuex组成和原理<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>组成: 组件间通信, 通过store实现全局存取</li> <li>修改: 唯一途径, 通过commit一个mutations(同步)或dispatch一个actions(异步)</li> <li>简写: 引入mapState、mapGetters、mapActions</li></ul> <h3 id="_8-vue-router的原理，例如hashhistory和history-interface这些东西要弄明白。其实看一下源码就好了，看不懂可以直接看解析的相关技术博客。"><a href="#_8-vue-router的原理，例如hashhistory和history-interface这些东西要弄明白。其实看一下源码就好了，看不懂可以直接看解析的相关技术博客。" class="header-anchor">#</a> 8.vue-router的原理，例如hashhistory和History interface这些东西要弄明白。其实看一下源码就好了，看不懂可以直接看解析的相关技术博客。</h3> <ul><li><a href="https://www.jianshu.com/p/e8b2529e472c" target="_blank" rel="noopener noreferrer">vue-router用法<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>:
在router.js或者某一个路由分发页面配置path, name, component对应关系
<ul><li>每个按钮一个value, 在watch功能中使用this.$router.push实现对应跳转, 类似react的this.history.push</li> <li>或直接用router-link to去跳转, 类似react的link to</li></ul></li> <li><a href="https://www.jianshu.com/p/4295aec31302" target="_blank" rel="noopener noreferrer">vue-router原理<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>: 通过<strong>hash</strong>和<strong>History interface</strong>两种方式实现前端路由
<ul><li>HashHistory: 利用URL中的hash（“#”）;replace()方法与push()方法不同之处在于，它并不是将新路由添加到浏览器访问历史的栈顶，而是替换掉当前的路由</li> <li>History interface: 是浏览器历史记录栈提供的接口，通过back(), forward(), go()等方法，我们可以读取浏览器历史记录栈的信息，进行各种跳转操作. pushState(), replaceState() 这下不仅是读取了，还可以对浏览器历史记录栈进行修改</li></ul></li></ul> <h3 id="_9-vue的seo问题"><a href="#_9-vue的seo问题" class="header-anchor">#</a> 9.vue的seo问题</h3> <p>seo关系到网站排名, vue搭建spa做前后端分离不好做seo, 可通过其他方法解决:</p> <ul><li><a href="https://ssr.vuejs.org/zh/#%E4%BB%80%E4%B9%88%E6%98%AF%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%AB%AF%E6%B8%B2%E6%9F%93-ssr-%EF%BC%9F" target="_blank" rel="noopener noreferrer">SSR服务端渲染<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>: 将同一个组件渲染为服务器端的 HTML 字符串.利于seo且更快.</li> <li>vue-meta-info, nuxt, prerender-spa-plugin页面预渲染等</li></ul> <h3 id="_10-预渲染和ssr"><a href="#_10-预渲染和ssr" class="header-anchor">#</a> 10.预渲染和ssr</h3> <p>以上</p> <h3 id="_11-生命周期内create和mounted的区别"><a href="#_11-生命周期内create和mounted的区别" class="header-anchor">#</a> 11.生命周期内create和mounted的区别</h3> <ul><li><strong>created</strong>: 在模板渲染成html前调用，即通常初始化某些数据，然后再渲染成视图。</li> <li><strong>mounted</strong>: 在模板渲染成html后调用，通常是初始化页面完成后，再对html的dom节点进行一些需要的操作和方法。</li></ul> <h3 id="_12-监听watch"><a href="#_12-监听watch" class="header-anchor">#</a> 12.监听watch</h3> <p>对应一个对象，键是观察表达式，值是对应回调。值也可以是methods的方法名，或者是对象，包含选项。在实例化时为每个键调用 $watch()</p> <h3 id="_13-登录验证拦截-通过router"><a href="#_13-登录验证拦截-通过router" class="header-anchor">#</a> 13.登录验证拦截(通过router)</h3> <ul><li>先设置requireAuth:</li></ul> <div class="language- line-numbers-mode"><pre class="language-text"><code>routes = [
    {
        name: 'detail',
        path: '/detail',
        meta: {
            requireAuth: true
        }
    },
    {
        name: 'login',
        path: '/login'
    }
]
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><ul><li>再配置router.beforeEach:</li></ul> <div class="language- line-numbers-mode"><pre class="language-text"><code>router.beforeEach((from, to, next) =&gt; {
    if (to.meta.requireAuth) { // 判断跳转的路由是否需要登录
        if (store.state.token) { // vuex.state判断token是否存在
            next() // 已登录
        } else {
            next({
                path: '/login',
                query: {redirect: to.fullPath} // 将跳转的路由path作为参数，登录成功后跳转到该路由
            })
        }
    } else {
       next()
    }
})
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><h3 id="_14-v-for-key值"><a href="#_14-v-for-key值" class="header-anchor">#</a> 14. v-for key值</h3> <p>不写key值会报warning, 和react的array渲染类似. 根据diff算法, 修改数组后, 写key值会复用, 不写会重新生成, 造成性能浪费或某些不必要的错误</p> <h3 id="_15-vue3-0的更新和defineproperty优化"><a href="#_15-vue3-0的更新和defineproperty优化" class="header-anchor">#</a> 15. <a href="https://www.oschina.net/news/101906/vue-3-0-updates?from=singlemessage" target="_blank" rel="noopener noreferrer">vue3.0的更新和defineProperty优化<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>放弃 Object.defineProperty ，使用更快的原生 Proxy (访问对象拦截器, 也称代理器)</li> <li>提速, 降低内存使用, Tree-shaking更友好</li> <li>支持IE11等</li> <li>使用Typescript</li></ul> <h3 id="_15-vue使用this获取变量"><a href="#_15-vue使用this获取变量" class="header-anchor">#</a> 15. vue使用this获取变量</h3> <p>正常要通过vm.$options.data访问，但实例vm会遍历data中的变量，并挂在到this上， this.$root传参取值</p> <h3 id="_16-jquery的优缺点，与vue的不同，vue的优缺点？"><a href="#_16-jquery的优缺点，与vue的不同，vue的优缺点？" class="header-anchor">#</a> 16.  <a href="https://www.jianshu.com/p/131c0d04dc1b" target="_blank" rel="noopener noreferrer">jQuery的优缺点，与vue的不同，vue的优缺点？<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>jq优点: 比原生js更易书写, 封装了很多api, 有丰富的插件库; 缺点: 每次升级与之前版本不兼容, 只能手动开发, 操作DOM很慢, 不方便, 变量名污染, 作用域混淆等.</li> <li>vue优缺点: 双向绑定, 虚拟DOM, diff算法, MVVM, 组件化, 通信方便, 路由分发等</li></ul> <h3 id="_17-vue解除双向绑定"><a href="#_17-vue解除双向绑定" class="header-anchor">#</a> 17. vue解除双向绑定</h3> <p><code>let obj = JSON.parse(JSON.stringify(this.temp1));</code></p> <h3 id="_18-vue异步组件"><a href="#_18-vue异步组件" class="header-anchor">#</a> 18. vue异步组件</h3> <p>为了简化，Vue 允许你以一个工厂函数的方式定义你的组件，这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数，且会把结果缓存起来供未来重渲染</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>Vue.component(
  'async-webpack-example',
  // 这个 `import` 函数会返回一个 `Promise` 对象。
  () =&gt; import('./my-async-component')
)
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h3 id="_19-mvc与mvvm"><a href="#_19-mvc与mvvm" class="header-anchor">#</a> 19. <a href="http://baijiahao.baidu.com/s?id=1596277899370862119&amp;wfr=spider&amp;for=pc" target="_blank" rel="noopener noreferrer">MVC与MVVM<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>model-数据层 view-视图层 controller-控制层</li> <li>MVC的目的是实现M和V的分离，单向通信，必须通过C来承上启下</li> <li>MVVM中通过VM（vue中的实例化对象）的发布者-订阅者模式实现双向绑定，数据绑定，dom事件监听</li> <li>区别：MVC和MVVM的区别并不是VM完全取代了C，ViewModel存在目的在于抽离Controller中展示的业务逻辑，而不是替代Controller，其它视图操作业务等还是应该放在Controller中实现。也就是说MVVM实现的是业务逻辑组件的重用</li></ul> <h3 id="_20-vue渐进式"><a href="#_20-vue渐进式" class="header-anchor">#</a> 20. vue渐进式</h3> <p>小到可以只使用核心功能，比如单文件组件作为一部分嵌入；大到使用整个工程，vue init webpack my-project来构建项目；VUE的核心库及其生态系统也可以满足你的各式需求（core+vuex+vue-route）</p> <h2 id="react相关"><a href="#react相关" class="header-anchor">#</a> react相关</h2> <h3 id="_1-新旧生命周期"><a href="#_1-新旧生命周期" class="header-anchor">#</a> 1. <a href="https://segmentfault.com/a/1190000016617400" target="_blank" rel="noopener noreferrer">新旧生命周期<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li><strong>旧</strong>: will, did; mount, update...</li> <li><strong>新</strong>: 16版本之后:
<ul><li><code>getDerivedStateFromProps</code>: 虚拟dom之后，实际dom挂载之前, 每次获取新的props或state之后, 返回新的state, 配合didUpdate可以替代willReceiveProps</li> <li><code>getSnapshotBeforeUpdate</code>: update发生的时候，组件更新前触发, 在render之后，在组件dom渲染之前；返回一个值，作为componentDidUpdate的第三个参数；配合componentDidUpdate, 可以覆盖componentWillUpdate的所有用法</li> <li><code>componentDidCatch</code>: 错误处理</li></ul></li> <li><strong>对比</strong>: 弃用了三个will, 新增两个get来代替will, 不能混用, 17版本会彻底删除. 新增错误处理</li></ul> <h3 id="_2-react核心"><a href="#_2-react核心" class="header-anchor">#</a> 2. react核心</h3> <ul><li><a href="http://www.cnblogs.com/mahmud/p/10099672.html" target="_blank" rel="noopener noreferrer">虚拟DOM, Diff算法, 遍历key值<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li> <li>react-dom: 提供了针对DOM的方法，比如：把创建的虚拟DOM，渲染到页面上 或 配合ref来操作DOM</li> <li>react-router</li></ul> <h3 id="_3-fiber核心-react-16"><a href="#_3-fiber核心-react-16" class="header-anchor">#</a> 3. fiber核心(react 16)</h3> <ul><li>旧: 浏览器渲染引擎单线程, 计算DOM树时锁住整个线程, 所有行为同步发生, 有效率问题, 期间react会一直占用浏览器主线程，如果组件层级比较深，相应的堆栈也会很深，长时间占用浏览器主线程, 任何其他的操作（包括用户的点击，鼠标移动等操作）都无法执行</li> <li>新: 重写底层算法逻辑, 引入fiber时间片, 异步渲染, react会在渲染一部分树后检查是否有更高优先级的任务需要处理(如用户操作或绘图), 处理完后再继续渲染, 并可以更新优先级, 以此管理渲染任务. 加入fiber的react将组件更新分为两个时期（phase 1 &amp;&amp; phase 2），render前的生命周期为phase1，render后的生命周期为phase2, 1可以打断, 2不能打断一次性更新. 三个will生命周期可能会重复执行, 尽量避免使用</li></ul> <h3 id="_4-渲染一个react"><a href="#_4-渲染一个react" class="header-anchor">#</a> 4. 渲染一个react</h3> <ul><li>分为首次渲染和更新渲染</li> <li>生命周期, 建立虚拟DOM, 进行diff算法</li> <li>对比新旧DOM, 节点对比, 将算法复杂度从O(n^3)降低到O(n)</li> <li>key值优化, 避免用index作为key值, 兄弟节点中唯一就行</li></ul> <h3 id="_5-高阶组件"><a href="#_5-高阶组件" class="header-anchor">#</a> 5. 高阶组件</h3> <p>高阶组件就是一个函数，且该函数(wrapper)接受一个组件作为参数，并返回一个新的组件。
高阶组件并不关心数据使用的方式和原因，而被包裹的组件也不关心数据来自何处.</p> <ul><li><a href="https://segmentfault.com/a/1190000004006185?_ea=457266" target="_blank" rel="noopener noreferrer">react-dnd<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>: 根组件, source, target等
<code>export default DragSource(type, spec, collect)(MyComponent)</code></li> <li>重构代码库使用HOC提升开发效率</li></ul> <h3 id="_6-hook-v16-7测试"><a href="#_6-hook-v16-7测试" class="header-anchor">#</a> 6. hook(v16.7测试)</h3> <p>在无状态组件(如函数式组件)中也能操作state以及其他react特性, 通过useState</p> <h3 id="_7-redux和vuex以及dva："><a href="#_7-redux和vuex以及dva：" class="header-anchor">#</a> 7. redux和vuex以及dva：</h3> <ul><li>redux: 通过store存储，通过action唯一更改，reducer描述如何更改。dispatch一个action</li> <li>dva: 基于redux，结合redux-saga等中间件进行封装</li> <li>vuex：类似dva，集成化。action异步，mutation非异步</li></ul> <h3 id="_8-react和vue的区别"><a href="#_8-react和vue的区别" class="header-anchor">#</a> 8. <a href="https://www.jianshu.com/p/b7cd52868e95?from=groupmessage" target="_blank" rel="noopener noreferrer">react和vue的区别<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li><strong>数据是否可变</strong>: react整体是函数式的思想，把组件设计成纯组件，状态和逻辑通过参数传入，所以在react中，是单向数据流，推崇结合immutable来实现数据不可变; vue的思想是响应式的，也就是基于是数据可变的，通过对每一个属性建立Watcher来监听，当属性变化的时候，响应式的更新对应的虚拟dom。总之，react的性能优化需要手动去做，而vue的性能优化是自动的，但是vue的响应式机制也有问题，就是当state特别多的时候，Watcher也会很多，会导致卡顿，所以大型应用（状态特别多的）一般用react，更加可控。</li> <li><strong>通过js来操作一切，还是用各自的处理方式</strong>: react的思路是all in js，通过js来生成html，所以设计了jsx，还有通过js来操作css，社区的styled-component、jss等; vue是把html，css，js组合到一起，用各自的处理方式，vue有单文件组件，可以把html、css、js写到一个文件中，html提供了模板引擎来处理。</li> <li><strong>类式的组件写法，还是声明式的写法</strong>: react是类式的写法，api很少; 而vue是声明式的写法，通过传入各种options，api和参数都很多。所以react结合typescript更容易一起写，vue稍微复杂。</li> <li><strong>扩展不同</strong>: react可以通过高阶组件（Higher Order Components--HOC）来扩展，而vue需要通过mixins来扩展</li> <li><strong>什么功能内置，什么交给社区去做</strong>: react做的事情很少，很多都交给社区去做，vue很多东西都是内置的，写起来确实方便一些，
比如 redux的combineReducer就对应vuex的modules，
比如reselect就对应vuex的getter和vue组件的computed，
vuex的mutation是直接改变的原始数据，而redux的reducer是返回一个全新的state，所以redux结合immutable来优化性能，vue不需要。</li></ul> <h3 id="_9-react单向数据流怎么理解"><a href="#_9-react单向数据流怎么理解" class="header-anchor">#</a> 9. react单向数据流怎么理解</h3> <p>React是单向数据流，数据主要从父节点传递到子节点（通过props）。如果顶层（父级）的某个props改变了，React会重渲染所有的子节点。</p> <h3 id="_10-react算法复杂度优化"><a href="#_10-react算法复杂度优化" class="header-anchor">#</a> 10. React算法复杂度优化</h3> <p>react树对比是按照层级去对比的， 他会给树编号0,1,2,3,4.... 然后相同的编号进行比较。 所以复杂度是n，这个好理解。</p> <p>关键是传统diff的复杂度是怎么算的？ 传统的diff需要出了上面的比较之外，还需要跨级比较。 他会将两个树的节点，两两比较，这就有n^2的复杂度了。 然后还需要编辑树，编辑的树可能发生在任何节点，需要对树进行再一次遍历操作，因此复杂度为n。加起来就是n^3了。</p> <h3 id="_11-react优点"><a href="#_11-react优点" class="header-anchor">#</a> 11. React优点</h3> <p>声明式, 组件化, 一次学习, 随处编写. 灵活, 丰富, 轻巧, 高效</p> <h3 id="_12-react事件机制"><a href="#_12-react事件机制" class="header-anchor">#</a> 12. React事件机制</h3> <ul><li>合成事件：
<ul><li>根据事件类型，采用不同的<code>SyntheticEvent</code>来构造不同的合成事件</li> <li><code>syntheticEvent</code> 和原生浏览器事件一样拥有同样的接口，也支持事件冒泡机制。可以通过<code>stopPropgation</code>和<code>preventDefault</code>中断</li> <li>如果需要访问原生事件对象，可以使用<code>nativeEvent</code>属性</li></ul></li> <li>实现机制：
<ul><li>react 的事件机制利用了事件委托机制</li> <li>没有绑定在真实的dom节点上，而是把事件都绑定在结构的最外层document，统一由这个监听器分发</li> <li>注册：组件挂载和更新时，将绑定事件分类放入<code>EventPluginHub</code>事件池</li> <li>触发：根据事件产生的Event对象找到触发事件的组件，再通过组件标识和事件类型从事件池里找到对应的事件监听回调并执行</li></ul></li> <li>react中使用原生
<ul><li>在<code>didmount</code>中对真实dom进行原生绑定，在<code>unmount</code>解绑，防止内存泄漏</li> <li><code>syntheticEvent</code>的<code>stopPropgation</code>无法阻止原生事件的冒泡，但原生可以组织合成，所以尽量不要混用，除非使用e.target判断</li></ul></li> <li>异步回调使用<code>syntheticEvent</code>：
<ul><li>合成事件里，回调执行后会销毁事件对象</li> <li>异步回调需使用<code>event.persist()</code>告诉react不要回收</li></ul></li> <li>与原生冒泡捕获对比：
<ul><li>原生的捕获机制并不常用，且具有 ie 的不兼容问题</li> <li>react仅实现冒泡机制，无兼容问题，只有<code>document</code>节点上才有 DOM 事件也节约了内存</li></ul></li> <li>事件执行：
<ol><li>找到事件触发的<code>DOM</code>和<code>React Component</code>，调用<code>findParent</code>方法</li> <li>遍历得到所有父组件，存在数组中</li> <li>从该组件直到最后一个父组件，根据之前事件存储，用 React 事件名 + 组件 key，找到对应绑定回调方法</li></ol></li></ul> <h2 id="移动端相关"><a href="#移动端相关" class="header-anchor">#</a> 移动端相关</h2> <h3 id="_1-移动端兼容适配"><a href="#_1-移动端兼容适配" class="header-anchor">#</a> 1. 移动端兼容适配</h3> <ul><li><meta name="viewport" content="width=device-width, initial-scale=1.0"></li> <li>rem, em, 百分比</li> <li>框架的栅格布局</li> <li>media query媒体查询</li> <li>手淘团队的一套flexible.js, 自动判断dpr进行整个布局视口的放缩</li></ul> <h3 id="_2-flexible如何实现自动判断dpr"><a href="#_2-flexible如何实现自动判断dpr" class="header-anchor">#</a> 2. flexible如何实现自动判断dpr</h3> <p>判断机型, 找出样本机型去适配. 比如iphone以6为样本, 宽度375px, dpr是2</p> <h3 id="_3-为什么以iphone6为标准的设计稿的尺寸是以750px宽度来设计的呢？"><a href="#_3-为什么以iphone6为标准的设计稿的尺寸是以750px宽度来设计的呢？" class="header-anchor">#</a> 3. 为什么以iPhone6为标准的设计稿的尺寸是以750px宽度来设计的呢？</h3> <p>iPhone6的满屏宽度是375px，而iPhone6采用的视网膜屏的物理像素是满屏宽度的2倍，也就是dpr(设备像素比)为2, 并且设计师所用的PS设计软件分辨率和像素关系是1:1。所以为了做出的清晰的页面，设计师一般给出750px的设计图，我们再根据需求对元素的尺寸设计和压缩。</p> <h3 id="_4-如何处理异形屏iphone-x"><a href="#_4-如何处理异形屏iphone-x" class="header-anchor">#</a> 4. 如何处理异形屏iphone X</h3> <ul><li><code>safe area</code>: 默认放置在安全区域以避免遮挡, 但会压缩</li> <li>在meta中添加<code>viewport-fit=cover</code>: 告诉浏览器要讲整个页面渲染到浏览器中，不管设备是圆角与否，这个时候会造成页面的元素被圆角遮挡</li> <li><code>padding: constant(env)</code>: 解决遮挡问题</li></ul> <h3 id="_5-移动端首屏优化"><a href="#_5-移动端首屏优化" class="header-anchor">#</a> 5. 移动端首屏优化</h3> <ul><li>采用服务器渲染ssr</li> <li>按需加载配合<a href="https://www.jb51.net/article/119160.htm" target="_blank" rel="noopener noreferrer">webpack分块打包<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>, 通过entry和commonChunkPlugin</li> <li>很有必要将script标签➕异步</li> <li>有轮播图 最好给个默认 另外要处理图片懒加载</li> <li><a href="https://www.jianshu.com/p/bd202dca29ad" target="_blank" rel="noopener noreferrer">打包线上也要注意去掉map 文件<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li> <li>组件, 路由懒加载</li> <li>webpack的一切配置 肯定是必须的</li> <li>压缩图片 <a href="https://tinypng.com/" target="_blank" rel="noopener noreferrer">https://tinypng.com/<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li> <li>建议还是用webpack的图片压缩插件</li> <li>骨架屏</li> <li>Loading页面</li></ul> <h3 id="_6-pwa全称progressive-web-app，即渐进式web应用"><a href="#_6-pwa全称progressive-web-app，即渐进式web应用" class="header-anchor">#</a> 6. <a href="https://segmentfault.com/a/1190000012353473?utm_source=tag-newest" target="_blank" rel="noopener noreferrer">PWA全称Progressive Web App，即渐进式WEB应用<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p>一个 PWA 应用首先是一个网页, 可以通过 Web 技术编写出一个网页应用. 随后添加上 App Manifest 和 Service Worker 来实现 PWA 的安装和离线等功能
解决了哪些问题？</p> <ul><li>可以添加至主屏幕，点击主屏幕图标可以实现启动动画以及隐藏地址栏</li> <li>实现离线缓存功能，即使用户手机没有网络，依然可以使用一些离线功能</li> <li>实现了消息推送
它解决了上述提到的问题，这些特性将使得 Web 应用渐进式接近原生 App。</li></ul> <h3 id="_7-离线包方案"><a href="#_7-离线包方案" class="header-anchor">#</a> 7. 离线包方案</h3> <p>现在 web 页面在移动端的地位越来越高，大部分主流 App 采用 native + webview 的 hybrid 模式，加载远程页面受限于网络，本地 webview 引擎，经常会出现渲染慢导致的白屏现象，体验很差，于是离线包方案应运而生。动态下载的离线包可以使得我们不需要走完整的 App 审核发布流程就完成了版本的更新</p> <h3 id="_8-自适应和响应式布局的区别"><a href="#_8-自适应和响应式布局的区别" class="header-anchor">#</a> 8. <a href="https://baijiahao.baidu.com/s?id=1627060039271152391&amp;wfr=spider&amp;for=pc" target="_blank" rel="noopener noreferrer">自适应和响应式布局的区别<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ol><li><p>自适应布局通过检测视口分辨率，来判断当前访问的设备是：pc端、平板、手机，从而请求服务层，返回不同的页面；响应式布局通过检测视口分辨率，针对不同客户端在客户端做代码处理，来展现不同的布局和内容。</p></li> <li><p>自适应布局需要开发多套界面，而响应式布局只需要开发一套界面就可以了。</p></li> <li><p>自适应对页面做的屏幕适配是在一定范围：比如pc端一般要大于1024像素，手机端要小于768像素。而响应式布局是一套页面全部适应。</p></li> <li><p>自适应布局如果屏幕太小会发生内容过于拥挤。而响应式布局正是为了解决这个问题而衍生出的概念，它可以自动识别屏幕宽度并做出相应调整的网页设计。</p></li></ol> <h2 id="插件及工具相关"><a href="#插件及工具相关" class="header-anchor">#</a> 插件及工具相关</h2> <h3 id="_1-babel和polyfill"><a href="#_1-babel和polyfill" class="header-anchor">#</a> 1. <a href="http://www.cnblogs.com/zhansu/p/8305081.html" target="_blank" rel="noopener noreferrer">babel和polyfill<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li><p><code>Babel</code>: Babel 是一个广泛使用的 ES6 转码器，可以将 ES6 代码转为 ES5 代码。注意：Babel 默认只转换新的 JavaScript 句法（syntax），而不转换新的 API</p></li> <li><p><code>Polyfill</code>: Polyfill的准确意思为，用于实现浏览器并不支持的原生API的代码。</p></li></ul> <h3 id="_2-jpg-jpeg和png区别"><a href="#_2-jpg-jpeg和png区别" class="header-anchor">#</a> 2. jpg, jpeg和png区别</h3> <ul><li>jpg是jpeg的缩写, 二者一致</li> <li>PNG就是为取代GIF而生的, 无损压缩, 占用内存多</li> <li>jpg牺牲图片质量, 有损, 占用内存小</li> <li>PNG格式可编辑。如图片中有字体等，可利用PS再做更改。JPG格式不可编辑</li></ul> <h3 id="_3-git-rebase和merge区别"><a href="#_3-git-rebase和merge区别" class="header-anchor">#</a> 3. <a href="https://www.jianshu.com/p/4079284dd970" target="_blank" rel="noopener noreferrer">git rebase和merge区别<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p><img src="https://upload-images.jianshu.io/upload_images/13102777-10c938ef31a111d6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="git rebase"> <img src="https://upload-images.jianshu.io/upload_images/13102777-d26dc5206211eef1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="git merge"></p> <h1 id="前端性能优化"><a href="#前端性能优化" class="header-anchor">#</a> 前端性能优化</h1> <ol><li>减少HTTP请求（合并css、js，雪碧图/base64图片）</li> <li>压缩（css、js、图片皆可压缩,使用webpack uglify和 svg）</li> <li>样式表放头部，脚本放底部</li> <li>使用CDN（这部分，不少前端都不用考虑，负责发布的兄弟可能会负责搞好）</li> <li>http缓存</li> <li>bosify图片压缩: 根据具体情况修改图片后缀或格式  后端根据格式来判断存储原图还是缩略图</li> <li>懒加载, 预加载</li> <li>替代方案: 骨架屏, SSR</li> <li><a href="https://segmentfault.com/a/1190000015883378?utm_source=tag-newest" target="_blank" rel="noopener noreferrer">webpack优化<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li></ol> <h2 id="原生通信"><a href="#原生通信" class="header-anchor">#</a> 原生通信</h2> <h3 id="_1-jsbridge通信原理-有哪几种实现的方式？"><a href="#_1-jsbridge通信原理-有哪几种实现的方式？" class="header-anchor">#</a> 1.<a href="https://blog.csdn.net/u014021258/article/details/81129702" target="_blank" rel="noopener noreferrer">JSBridge通信原理, 有哪几种实现的方式？<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p>JsBridge给JavaScript提供了调用Native功能，Native也能够操控JavaScript。这样前端部分就可以方便使用地理位置、摄像头以及登录支付等Native能力啦。JSBridge构建 Native和非Native间消息通信的通道，而且是 双向通信的通道。</p> <ul><li>JS 向 Native 发送消息 : 调用相关功能、通知 Native 当前 JS 的相关状态等。</li> <li>Native 向 JS 发送消息 : 回溯调用结果、消息推送、通知 JS 当前 Native 的状态等。</li></ul> <p>2.实现一个简单的 JSBridge，设计思路？</p> <h2 id="算法相关"><a href="#算法相关" class="header-anchor">#</a> 算法相关</h2> <h3 id="_1-二分查找和冒泡排序"><a href="#_1-二分查找和冒泡排序" class="header-anchor">#</a> 1. <a href="https://www.cnblogs.com/tine/p/5938844.html" target="_blank" rel="noopener noreferrer">二分查找和冒泡排序<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>二分查找: 递归(分左右, 传递start,end参数)和非递归(使用while(l &lt; h))；要求有序数组</li> <li>冒泡排序: 两个for循环</li></ul> <h3 id="_2-快速排序"><a href="#_2-快速排序" class="header-anchor">#</a> 2. <a href="https://www.jianshu.com/p/e394f7012d75" target="_blank" rel="noopener noreferrer">快速排序<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>function quickSort (arr) {
  if (arr.length &lt; 2) return arr
  var middle = Math.floor(arr.length / 2)
  var flag = arr.splice(middle, 1)[0]
  var left = [],
        right = []
  for (var i = 0; i &lt; arr.length; i++) {
    if (arr[i] &lt; flag) {
      left.push(arr[i])
    } else {
      right.push(arr[i])
    }
  }
  return quickSort(left).concat([flag], quickSort(right))
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><h3 id="_3-最长公共子串"><a href="#_3-最长公共子串" class="header-anchor">#</a> 3. 最长公共子串</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>function findSubStr(str1, str2) {
        if (str1.length &gt; str2.length) {
          [str1, str2] = [str2, str1]
        }
        var result = ''
        var len = str1.length
        for (var j = len; j &gt; 0; j--) {
          for (var i = 0; i &lt; len - j; i++) {
            result = str1.substr(i, j)
            if (str2.includes(result)) return result
          }
        }
      }
      console.log(findSubStr('aabbcc11', 'ppooiiuubcc123'))
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><h3 id="_4-最长公共子序列-lcs动态规划"><a href="#_4-最长公共子序列-lcs动态规划" class="header-anchor">#</a> 4. <a href="https://juejin.im/post/5b0c2583f265da08f50b4b33#heading-0" target="_blank" rel="noopener noreferrer">最长公共子序列(LCS动态规划)<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p><a href="https://segmentfault.com/a/1190000012864957" target="_blank" rel="noopener noreferrer">另一篇<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p> <div class="language- line-numbers-mode"><pre class="language-text"><code>// dp[i][j] 计算去最大长度，记住口诀：相等左上角加一，不等取上或左最大值
function LCS(str1, str2){
        var rows =  str1.split(&quot;&quot;)
        rows.unshift(&quot;&quot;)
        var cols =  str2.split(&quot;&quot;)
        cols.unshift(&quot;&quot;)
        var m = rows.length 
        var n = cols.length 
        var dp = []
        for(var i = 0; i &lt; m; i++){ 
            dp[i] = []
            for(var j = 0; j &lt; n; j++){ 
                if(i === 0 || j === 0){
                    dp[i][j] = 0
                    continue
                }
              
                if(rows[i] === cols[j]){ 
                    dp[i][j] = dp[i-1][j-1] + 1 //对角＋1
                }else{
                    dp[i][j] = Math.max( dp[i-1][j], dp[i][j-1]) //对左边，上边取最大
                }
            }
            console.log(dp[i].join(&quot;&quot;))//调试
        } 
        return dp[i-1][j-1]
    }
//!!!如果它来自左上角加一，则是子序列，否则向左或上回退。
//findValue过程，其实就是和 就是把T[i][j]的计算反过来。
// 求最长子序列
function findValue(input1,input2,n1,n2,T){
	var i = n1-1,j=n2-1;
	var result = [];//结果保存在数组中
	console.log(i);
	console.log(j);
	while(i&gt;0 &amp;&amp; j&gt;0){
		if(input1[i] == input2[j]){
			result.unshift(input1[i]);
			i--;
			j--;
		}else{
			//向左或向上回退
			if(T[i-1][j]&gt;T[i][j-1]){
				//向上回退
				i--;
			}else{
				//向左回退
				j--;
			}
		}

	}

	console.log(result);
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br></div></div><h3 id="_5-数组去重，多种方法"><a href="#_5-数组去重，多种方法" class="header-anchor">#</a> 5. <a href="https://www.cnblogs.com/guangyan/articles/6682686.html" target="_blank" rel="noopener noreferrer">数组去重，多种方法<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <ul><li>双for循环, splice剔除并i--回退</li> <li>indexOf等于index</li> <li>filter indexOf === index</li> <li>新数组indexOf === index</li> <li>使用空对象等</li></ul> <h3 id="_6-实现一个函数功能：sum-1-2-3-4-n-转化为-sum-1-2-3-4-…-n"><a href="#_6-实现一个函数功能：sum-1-2-3-4-n-转化为-sum-1-2-3-4-…-n" class="header-anchor">#</a> 6. 实现一个函数功能：sum(1,2,3,4..n)转化为 sum(1)(2)(3)(4)…(n)</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 使用柯里化 + 递归
function curry ( fn ) {
  var c = (...arg) =&gt; (fn.length === arg.length) ? 
          fn (...arg) : (...arg1) =&gt; c(...arg, ...arg1)
  return c
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p><a href="https://www.jianshu.com/p/7fa99a4bee8b" target="_blank" rel="noopener noreferrer">柯里化参考我的另一篇<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p> <h3 id="_7-反转二叉树"><a href="#_7-反转二叉树" class="header-anchor">#</a> 7. 反转二叉树</h3> <p>此题充满了嘲讽。。</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>var invertTree = function (root) {
  if (root !== null) {
    [root.left, root.right] = [root.right, root.left]
    invertTree(root.left)
    invertTree(root.right)
  }
  return root
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><h3 id="_8-贪心算法解决背包问题"><a href="#_8-贪心算法解决背包问题" class="header-anchor">#</a> 8. 贪心算法解决背包问题</h3> <p>问题：给定背包容积，如何存放不同重量和价值物品，能获得最大价值？</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>var items = ['A','B','C','D'] // 物品编号
var values = [50,220,60,60] // 物品价值
var weights = [5,20,10,12] // 物品重量
var capacity = 32 // 背包容积

greedy(values, weights, capacity) // 320

function greedy(values, weights, capacity) {
        var result = 0
        var rest = capacity
        var sortArray = []
        var num = 0
        values.forEach((v, i) =&gt; {
          sortArray.push({
            value: v,
            weight: weights[i],
            ratio: v / weights[i]
          })
        })
        // 按照性价比降序排序
        sortArray.sort((a, b) =&gt; b.ratio - a.ratio)
        sortArray.forEach((v, i) =&gt; {
          num = parseInt(rest / v.weight)
          rest -= num * v.weight
          result += num * v.value
        })
        return result
      }
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br></div></div><h3 id="_9-输入一个递增排序的数组和一个数字s，在数组中查找两个数，使得他们的和正好是s，如果有多对数字的和等于s，输出两个数的乘积最小的。"><a href="#_9-输入一个递增排序的数组和一个数字s，在数组中查找两个数，使得他们的和正好是s，如果有多对数字的和等于s，输出两个数的乘积最小的。" class="header-anchor">#</a> 9. 输入一个递增排序的数组和一个数字S，在数组中查找两个数，使得他们的和正好是S，如果有多对数字的和等于S，输出两个数的乘积最小的。</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>function FindNumbersWithSum(array, sum)
{
    var index = 0
    for (var i = 0; i &lt; array.length - 1 &amp;&amp; array[i] &lt; sum / 2; i++) {
        for (var j = i + 1; j &lt; array.length; j++) {
            if (array[i] + array[j] === sum) return [array[i], array[j]]
        }
        //index = array.indexOf(sum - array[i], i + 1)
       // if (index !== -1) {
       //     return [array[i], array[index]]
        //}
    }
    return []
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><h3 id="_10-二叉树各种-层序-遍历"><a href="#_10-二叉树各种-层序-遍历" class="header-anchor">#</a> 10. <a href="https://www.jianshu.com/p/3eee17f3c6f4" target="_blank" rel="noopener noreferrer">二叉树各种(层序)遍历<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p><a href="https://www.jianshu.com/p/5e9ea25a1aae" target="_blank" rel="noopener noreferrer">深度广度遍历<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></p> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 根据前序和中序重建二叉树
/* function TreeNode(x) {
    this.val = x;
    this.left = null;
    this.right = null;
} */
function reConstructBinaryTree(pre, vin)
{
    var result = null
    if (pre.length === 1) {
        result = {
            val: pre[0],
            left: null,
            right: null
        }
    } else if (pre.length &gt; 1) {
        var root = pre[0]
        var vinRootIndex = vin.indexOf(root)
        var vinLeft = vin.slice(0, vinRootIndex)
        var vinRight = vin.slice(vinRootIndex + 1, vin.length)
        pre.shift()
        var preLeft = pre.slice(0, vinLeft.length)
        var preRight = pre.slice(vinLeft.length, pre.length)
        result = {
            val: root,
            left: reConstructBinaryTree(preLeft, vinLeft),
            right: reConstructBinaryTree(preRight, vinRight)
        }
    }
    return result
}

// 递归
// 前序遍历
function prevTraverse (node) {
  if (node === null) return;

  console.log(node.data);
  prevTraverse(node.left);
  prevTraverse(node.right);
}

// 中序遍历
function middleTraverse (node) {
  if (node === null) return;

  middleTraverse(node.left);
  console.log(node.data);
  middleTraverse(node.right);
}

// 后序遍历
function lastTraverse (node) {
  if (node === null) return;

  lastTraverse(node.left);
  lastTraverse(node.right);
  console.log(node.data);
}

// 非递归
// 前序遍历
function preTraverse(tree) {
        var arr = [],
          node = null
        arr.unshift(tree)
        while (arr.length) {
          node = arr.shift()
          console.log(node.root)
          if (node.right) arr.unshift(node.right)
          if (node.left) arr.unshift(node.left)
        }
      }

// 中序遍历
function middleTraverseUnRecursion (root) {
  let arr = [],
      node = root;

  while (arr.length !== 0 || node !== null) {
    if (node === null) {
      node = arr.shift();
      console.log(node.data);
      node = node.right;
    } else {
      arr.unshift(node);
      node = node.left;
    }
  }

}

// 广度优先-层序遍历
// 递归
var result = []
var stack = [tree]
var count = 0
var bfs = function () {
  var node = stack[count]
  if (node) {
    result.push(node.value)
    if (node.left) stack.push(node.left)
    if (node.right) stack.push(node.right)
    count++
    bfs()
  }
}
bfs()
console.log(result)
// 非递归
function bfs (node) {
  var result = []
  var queue = []
  queue.push(node)
  while (queue.length) {
    node = queue.shift()
    result.push(node.value)
    node.left &amp;&amp; queue.push(node.left)
    node.right &amp;&amp; queue.push(node.right)
  }
  return result
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br><span class="line-number">120</span><br><span class="line-number">121</span><br><span class="line-number">122</span><br></div></div><h3 id="_11-各种排序"><a href="#_11-各种排序" class="header-anchor">#</a> 11. <a href="https://www.jianshu.com/p/7e6589306a27" target="_blank" rel="noopener noreferrer">各种排序<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 插入排序
function insertSort(arr) {
        var temp
        for (var i = 1; i &lt; arr.length; i++) {
          temp = arr[i]
          for (var j = i; j &gt; 0 &amp;&amp; temp &lt; arr[j - 1]; j--) {
            arr[j] = arr[j - 1]
          }
          arr[j] = temp
        }
        return arr
      }
      console.log(insertSort([3, 1, 8, 2, 5]))

// 归并排序
function mergeSort(array) {
        var result = array.slice(0)
        function sort(array) {
          var length = array.length
          var mid = Math.floor(length * 0.5)
          var left = array.slice(0, mid)
          var right = array.slice(mid, length)
          if (length === 1) return array
          return merge(sort(left), sort(right))
        }
        function merge(left, right) {
          var result = []

          while (left.length || right.length) {
            if (left.length &amp;&amp; right.length) {
              if (left[0] &lt; right[0]) {
                result.push(left.shift())
              } else {
                result.push(right.shift())
              }
            } else if (left.length) {
              result.push(left.shift())
            } else {
              result.push(right.shift())
            }
          }
          return result
        }
        return sort(result)
      }
      console.log(mergeSort([5, 2, 8, 3, 6]))

// 二分插入排序
function twoSort(array) {
        var len = array.length,
          i,
          j,
          tmp,
          low,
          high,
          mid,
          result
        result = array.slice(0)
        for (i = 1; i &lt; len; i++) {
          tmp = result[i]
          low = 0
          high = i - 1
          while (low &lt;= high) {
            mid = parseInt((high + low) / 2, 10)
            if (tmp &lt; result[mid]) {
              high = mid - 1
            } else {
              low = mid + 1
            }
          }
          for (j = i - 1; j &gt;= high + 1; j--) {
            result[j + 1] = result[j]
          }
          result[j + 1] = tmp
        }
        return result
      }
      console.log(twoSort([4, 1, 7, 2, 5]))
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br></div></div><h3 id="_12-使用尾递归对斐波那契优化"><a href="#_12-使用尾递归对斐波那契优化" class="header-anchor">#</a> 12. <a href="http://es6.ruanyifeng.com/#docs/function#%E5%B0%BE%E8%B0%83%E7%94%A8%E4%BC%98%E5%8C%96" target="_blank" rel="noopener noreferrer">使用尾递归对斐波那契优化<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p>递归非常耗费内存，因为需要同时保存成千上百个调用帧，很容易发生“栈溢出”错误（stack overflow）。但对于尾递归来说，由于只存在一个调用帧，所以永远不会发生“栈溢出”错误。</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>// 传统递归斐波那契, 会造成超时或溢出
function Fibonacci (n) {
  if ( n &lt;= 1 ) {return 1};

  return Fibonacci(n - 1) + Fibonacci(n - 2);
}

Fibonacci(10) // 89
Fibonacci(100) // 超时
Fibonacci(500) // 超时

// 使用尾递归优化, 可规避风险
function Fibonacci2 (n , ac1 = 1 , ac2 = 1) {
  if( n &lt;= 1 ) {return ac2};

  return Fibonacci2 (n - 1, ac2, ac1 + ac2);
}

Fibonacci2(100) // 573147844013817200000
Fibonacci2(1000) // 7.0330367711422765e+208
Fibonacci2(10000) // Infinity
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div><h3 id="_13-两个升序数组合并为一个升序数组"><a href="#_13-两个升序数组合并为一个升序数组" class="header-anchor">#</a> 13. 两个升序数组合并为一个升序数组</h3> <div class="language- line-numbers-mode"><pre class="language-text"><code>function sort (A, B) {
  var i = 0, j = 0, p = 0, m = A.length, n = B.length, C = []
  while (i &lt; m || j &lt; n) {
    if (i &lt; m &amp;&amp; j &lt; n) {
      C[p++] = A[i] &lt; B[j] ? A[i++] : B[j++]
    } else if (i &lt; m) {
      C[p++] = A[i++]
    } else {
      C[p++] = B[j++]
    }
  }
  return C
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><h2 id="node相关"><a href="#node相关" class="header-anchor">#</a> node相关</h2> <h3 id="_1-node的router是什么"><a href="#_1-node的router是什么" class="header-anchor">#</a> 1. node的router是什么</h3> <h3 id="_2-数据库索引是啥"><a href="#_2-数据库索引是啥" class="header-anchor">#</a> 2. 数据库索引是啥</h3> <ul><li>狭义上: 索引是数据库针对每条数据自动生成的内部唯一id标识, 用以快速搜索定位数据</li> <li>广义上: 是数据库根据每条数据形成的关键字, 将划分为树形结构, 便于sql语句对数据的查找, 使算法复杂度降低到O(logn)</li></ul> <h3 id="_3-浏览器的事件循环和node事件循环有什么区别？"><a href="#_3-浏览器的事件循环和node事件循环有什么区别？" class="header-anchor">#</a> 3. <a href="https://www.jianshu.com/p/b221e6e36dcb" target="_blank" rel="noopener noreferrer">浏览器的事件循环和node事件循环有什么区别？<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></h3> <p>微任务执行时机不同：
Node环境：微任务在事件循环的各个阶段的 空隙（中间）执行
浏览器：微任务在事件循环的宏任务执行完后执行</p> <h3 id="_4-关于buffer"><a href="#_4-关于buffer" class="header-anchor">#</a> 4. 关于buffer</h3> <ul><li>node中的核心对象：<code>Buffer.from(str)</code></li> <li>用来存储二进制数据的类数组</li> <li>用两位十六进制数表示一个字符的<code>unicode</code>编码</li> <li>连续存储空间，快</li> <li>1 byte = 8 bit</li> <li>英文字符1 byte, 中文字符2 byte</li></ul> <h1 id="计算机基础"><a href="#计算机基础" class="header-anchor">#</a> 计算机基础</h1> <ul><li>硬件：
<ul><li>CPU是人的大脑，负责运算</li> <li>内存是人的记忆，负责临时存储</li> <li>硬盘是人的笔记本，负责永久存储</li> <li>输入设备是人的耳朵或眼睛，负责接受外部的信息传给CPU</li> <li>以上所有的设备都通过总线连接，总线相当于人的神经</li></ul></li> <li>数据结构与算法：
<ul><li>算法：
<ul><li>定义：解决具体问题所需要的解决方法。</li> <li>最优算法：执行效率最快的，时间复杂度最低。</li> <li>特征：输入，输出，有穷性，确定性，可行性。</li> <li>类型：冒泡排序，二叉树遍历，最长回文，二分查找，指针，链表等，堆栈，队列等。</li> <li>途径：力扣，codewar，算法导论。</li></ul></li> <li>数据结构：
<ul><li>逻辑结构：集合、线性、树形、图形结构</li> <li>物理结构：顺序、链式存储结构</li></ul></li></ul></li> <li>操作系统：
<ul><li>定义：管理计算机硬件与软件资源的计算机程序，同时也是计算机系统的内核与基石</li> <li>功能：
<ul><li>管理与配置内存</li> <li>决定系统资源供需的优先次序</li> <li>控制输入设备与输出设备</li> <li>操作网络</li> <li>管理文件系统</li></ul></li></ul></li> <li>数据库：
<ul><li>关系型数据库比如MySQL、SQLServer、Oracle</li> <li>非关系型数据库mongodb</li></ul></li> <li>计算机组成原理：硬件和软件</li> <li>计算机网络：
<ul><li>定义：一些相互连接的、以共享资源为目的的、自治的计算机的集合</li> <li>组成：计算机、网络操作系统、传输介质以及相应的应用软件四部分</li> <li>功能：数据通信、资源共享、集中管理、分布式处理、负载均衡</li> <li>分类：局域网LAN、无线网</li> <li>网络协议TCP/IP</li></ul></li></ul></div> <footer class="page-edit"><!----> <!----></footer> <!----> </main></div><div class="global-ui"></div></div>
    <script src="/assets/js/app.395fbd21.js" defer></script><script src="/assets/js/2.cdd4cc35.js" defer></script><script src="/assets/js/10.69995dd9.js" defer></script>
  </body>
</html>
